pax_global_header00006660000000000000000000000064152256410350014515gustar00rootroot0000000000000052 comment=0148a6517b3b29de86849e1dedab0bb1bfe3344a quill-12.1.0/000077500000000000000000000000001522564103500127245ustar00rootroot00000000000000quill-12.1.0/.clang-format000066400000000000000000000025441522564103500153040ustar00rootroot00000000000000AccessModifierOffset: -2 AlignConsecutiveDeclarations: None AlignOperands: false AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: Never AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: Yes BinPackParameters: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Allman BreakBeforeTernaryOperators: true BreakConstructorInitializers: BeforeColon ColumnLimit: 100 CommentPragmas: '' ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 2 ContinuationIndentWidth: 2 DisableFormat: false ExperimentalAutoDetectBinPacking: false IndentCaseLabels: false IndentPPDirectives: BeforeHash IndentWidth: 2 IndentWrappedFunctionNames: false MaxEmptyLinesToKeep: 1 NamespaceIndentation: None PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakString: 1000 PenaltyBreakFirstLessLess: 120 PenaltyExcessCharacter: 1 PenaltyReturnTypeOnItsOwnLine: 1000 PointerAlignment: Left QualifierAlignment: Right LineEnding: LF SpaceBeforeAssignmentOperators: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInCStyleCastParentheses: false SpacesInParentheses: false Cpp11BracedListStyle: true Standard: c++20 TabWidth: 2 UseTab: Never quill-12.1.0/.codecov.yml000066400000000000000000000001111522564103500151400ustar00rootroot00000000000000ignore: - "docs" - "examples" - "include/quill/bundled" - "test" quill-12.1.0/.github/000077500000000000000000000000001522564103500142645ustar00rootroot00000000000000quill-12.1.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001522564103500164475ustar00rootroot00000000000000quill-12.1.0/.github/ISSUE_TEMPLATE/bug-report.md000066400000000000000000000011751522564103500210630ustar00rootroot00000000000000--- name: Bug report about: Report issues or errors to help us fix them title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behaviour if possible **Expected Behaviour** A clear and concise description of what you expected to happen. **Environment Details** - Library Version: Which version of the library are you using? - Operating System: Provide details (e.g., Windows 10, macOS 11.2, Ubuntu 20.04). - Compiler: Which compiler and version are you using? **Additional context** Add any other context about the problem here. quill-12.1.0/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000007161522564103500222000ustar00rootroot00000000000000--- name: Feature request about: Propose new features or improvements title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Additional context** Add any other context or screenshots about the feature request here. quill-12.1.0/.github/ISSUE_TEMPLATE/ideas---questions.md000066400000000000000000000001701522564103500222360ustar00rootroot00000000000000--- name: Ideas & Questions about: Share general suggestions or ask questions title: '' labels: '' assignees: '' --- quill-12.1.0/.github/workflows/000077500000000000000000000000001522564103500163215ustar00rootroot00000000000000quill-12.1.0/.github/workflows/bsd.yml000066400000000000000000000074001522564103500176150ustar00rootroot00000000000000name: BSD concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: FreeBSD: runs-on: ubuntu-latest timeout-minutes: 60 strategy: matrix: build_type: [ Release ] steps: - name: Checkout code uses: actions/checkout@v5 - name: FreeBSD Build and Test (${{ matrix.build_type }}) uses: vmactions/freebsd-vm@v1 with: release: '14.2' arch: 'x86_64' mem: 16384 cpu: 4 usesh: true prepare: | pkg install -y cmake run: | cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=17 -DQUILL_VERBOSE_MAKEFILE=ON -DQUILL_BUILD_TESTS=ON -DQUILL_BUILD_EXAMPLES=ON "$GITHUB_WORKSPACE" cmake --build . --config ${{ matrix.build_type }} --parallel 4 ctest --build-config ${{ matrix.build_type }} --output-on-failure -R "^multi_frontend_threads$" NetBSD: runs-on: ubuntu-latest timeout-minutes: 60 strategy: matrix: build_type: [ Release ] steps: - name: Checkout code uses: actions/checkout@v5 - name: NetBSD Build and Test (${{ matrix.build_type }}) uses: vmactions/netbsd-vm@v1 with: release: '10.0' arch: 'x86_64' mem: 16384 cpu: 4 usesh: true prepare: | /usr/sbin/pkg_add cmake run: | cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=17 -DQUILL_VERBOSE_MAKEFILE=ON -DQUILL_BUILD_TESTS=ON -DQUILL_BUILD_EXAMPLES=ON "$GITHUB_WORKSPACE" cmake --build . --config ${{ matrix.build_type }} --parallel 4 ctest --build-config ${{ matrix.build_type }} --output-on-failure -R "^multi_frontend_threads$" OpenBSD: runs-on: ubuntu-latest timeout-minutes: 60 strategy: matrix: build_type: [ Release ] steps: - name: Checkout code uses: actions/checkout@v5 - name: OpenBSD Build and Test (${{ matrix.build_type }}) uses: vmactions/openbsd-vm@v1 with: release: '7.7' arch: 'x86_64' mem: 16384 cpu: 4 usesh: true prepare: | pkg_add cmake run: | cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=17 -DQUILL_VERBOSE_MAKEFILE=ON -DQUILL_BUILD_TESTS=ON -DQUILL_BUILD_EXAMPLES=ON "$GITHUB_WORKSPACE" cmake --build . --config ${{ matrix.build_type }} --parallel 4 ctest --build-config ${{ matrix.build_type }} --output-on-failure -R "^multi_frontend_threads$" DragonFlyBSD: runs-on: ubuntu-latest timeout-minutes: 60 strategy: matrix: build_type: [ Release ] steps: - name: Checkout code uses: actions/checkout@v5 - name: DragonFly Build and Test (${{ matrix.build_type }}) uses: vmactions/dragonflybsd-vm@v1 with: release: '6.4.2' mem: 16384 cpu: 4 usesh: true prepare: | pkg install -y cmake gcc11 run: | cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_C_COMPILER=$(which gcc11) -DCMAKE_CXX_COMPILER=$(which g++11) -DCMAKE_CXX_STANDARD=17 -DQUILL_VERBOSE_MAKEFILE=ON -DQUILL_BUILD_TESTS=ON -DQUILL_BUILD_EXAMPLES=ON "$GITHUB_WORKSPACE" cmake --build . --config ${{ matrix.build_type }} --parallel 4 ctest --build-config ${{ matrix.build_type }} --output-on-failure -R "^multi_frontend_threads$" quill-12.1.0/.github/workflows/clang-windows.yml000066400000000000000000000037511522564103500216260ustar00rootroot00000000000000name: Clang-Windows concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: clang_msvc: runs-on: windows-2022 timeout-minutes: 60 strategy: matrix: compiler: [ clang-cl ] build_type: [ Debug, Release ] std: [ 17 ] steps: - uses: actions/checkout@v5 - name: Install LLVM uses: KyleMayes/install-llvm-action@v2 with: version: "19.1.7" - name: Create Build Directory run: cmake -E make_directory ${{runner.workspace}}/build - name: Configure with Clang shell: bash working-directory: ${{ github.workspace }} run: | # Set compiler paths based on matrix selection if [[ "${{ matrix.compiler }}" == "clang++" ]]; then C_COMPILER="clang" CXX_COMPILER="clang++" else C_COMPILER="clang-cl" CXX_COMPILER="clang-cl" fi cmake -S . -B "${{ runner.workspace }}/build" -G "Ninja" \ -DCMAKE_C_COMPILER="$C_COMPILER" \ -DCMAKE_CXX_COMPILER="$CXX_COMPILER" \ -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} \ -DQUILL_BUILD_TESTS=ON \ -DQUILL_BUILD_EXAMPLES=ON \ -DQUILL_VERBOSE_MAKEFILE=ON - name: Build working-directory: ${{runner.workspace}}/build run: | $threads = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors cmake --build . --config ${{matrix.build_type}} --parallel $threads - name: Test working-directory: ${{runner.workspace}}/build run: | ctest --build-config ${{matrix.build_type}} --output-on-failurequill-12.1.0/.github/workflows/coverage.yml000066400000000000000000000014661522564103500206460ustar00rootroot00000000000000name: Coverage concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: build: runs-on: ubuntu-22.04 timeout-minutes: 60 steps: - uses: actions/checkout@v5 - name: Configure 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 - name: Build run: cmake --build build -j4 - name: Test run: | cd build ctest --build-config Debug - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} verbose: true quill-12.1.0/.github/workflows/fedora.yml000066400000000000000000000034671522564103500203160ustar00rootroot00000000000000name: Fedora concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: build: runs-on: ubuntu-latest timeout-minutes: 60 container: fedora:40 strategy: fail-fast: false matrix: cxx: [g++] build_type: [Debug, Release] std: [23] with_tests: [ON] include: - cxx: g++ install: | dnf --setopt=retries=5 update -y dnf --setopt=retries=5 install -y gcc-c++ cmake make steps: - uses: actions/checkout@v5 - name: Install dependencies and create build environment run: | ${{ matrix.install }} mkdir -p ${{runner.workspace}}/build ls -l ${{runner.workspace}} - name: Configure env: CXX: ${{matrix.cxx}} CXXFLAGS: ${{matrix.cxxflags}} run: | cd ${{runner.workspace}}/build cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} ${{matrix.cmake_options}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} -DQUILL_BUILD_TESTS=${{matrix.with_tests}} \ -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build run: | cd ${{runner.workspace}}/build cmake --build . --config ${{ matrix.build_type }} --parallel $(nproc) - name: Test run: | cd ${{runner.workspace}}/build ctest --build-config ${{ matrix.build_type }} ${{ matrix.ctest_options }} --parallel $(nproc) --output-on-failure env: CTEST_OUTPUT_ON_FAILURE: True quill-12.1.0/.github/workflows/fuzz.yml000066400000000000000000000052261522564103500200470ustar00rootroot00000000000000name: Fuzz concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: fuzz: name: Run ${{ matrix.fuzzer }} runs-on: ubuntu-22.04 timeout-minutes: 60 strategy: fail-fast: false matrix: fuzzer: - FUZZ_BasicTypes - FUZZ_StlContainers - FUZZ_UserDefinedDeferredFormat - FUZZ_UserDefinedDirectFormat - FUZZ_QueueStress - FUZZ_QueueConfiguration - FUZZ_MegaEventCodec - FUZZ_JsonStructuredLogging - FUZZ_BinaryData - FUZZ_Multithread - FUZZ_DynamicLogLevel - FUZZ_LoggerLifecycle - FUZZ_RotatingSink - FUZZ_BacktraceStateMachine - FUZZ_MultiSinkFilter - FUZZ_MdcState steps: - uses: actions/checkout@v5 - name: Prepare run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-19 main" sudo apt-get update for i in {1..3}; do sudo apt-get -o Acquire::Retries=3 install -y clang-19 libc++-19-dev libc++abi-19-dev && break || sleep 15 done sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 sudo apt-get clean sudo rm -rf /var/lib/apt/lists/* echo "Disk after cleanup:" df -h cmake -E make_directory ${{runner.workspace}}/build - name: Configure working-directory: ${{runner.workspace}}/build env: CXX: clang++-19 run: | cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_STANDARD=17 -DQUILL_BUILD_FUZZING=ON \ -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build working-directory: ${{runner.workspace}}/build run: | threads=`nproc` cmake --build . --config Release --parallel $threads - name: Run fuzzer ${{ matrix.fuzzer }} working-directory: ${{runner.workspace}} run: | python3 quill/fuzz/run_fuzzers.py \ --duration 480 \ --fuzzer ${{ matrix.fuzzer }} \ --fuzzer-dir build/build/test quill-12.1.0/.github/workflows/gcc-recent.yml000066400000000000000000000033611522564103500210610ustar00rootroot00000000000000name: gcc-recent concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: build: name: GCC ${{ matrix.gcc_version }} ${{ matrix.build_type }} C++${{ matrix.std }} runs-on: ubuntu-latest timeout-minutes: 60 container: image: gcc:${{ matrix.gcc_version }} strategy: fail-fast: false matrix: gcc_version: [ "15.1", "16" ] cxx: [ g++ ] build_type: [ Debug, Release ] std: [ 23 ] with_tests: [ ON ] steps: - uses: actions/checkout@v5 - name: Install dependencies and create build environment run: | apt-get update apt-get install -y cmake make mkdir -p ${{runner.workspace}}/build ls -l ${{runner.workspace}} - name: Configure env: CXX: ${{matrix.cxx}} run: | cd ${{runner.workspace}}/build cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} -DQUILL_BUILD_TESTS=${{matrix.with_tests}} \ -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build run: | cd ${{runner.workspace}}/build cmake --build . --config ${{ matrix.build_type }} --parallel $(nproc) - name: Test run: | cd ${{runner.workspace}}/build ctest --build-config ${{ matrix.build_type }} --parallel $(nproc) --output-on-failure env: CTEST_OUTPUT_ON_FAILURE: True quill-12.1.0/.github/workflows/intelllvm.yml000066400000000000000000000047101522564103500210540ustar00rootroot00000000000000name: intelllvm concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: build: runs-on: ubuntu-latest timeout-minutes: 60 strategy: fail-fast: false matrix: build_type: [ Debug, Release ] std: [ 17 ] with_tests: [ ON ] steps: - uses: actions/checkout@v5 - name: Install Intel oneAPI DPC++ Compiler 2025.2.1 run: | wget -qO- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | sudo tee /etc/apt/trusted.gpg.d/GPG-PUB-KEY-INTEL-SW-PRODUCTS.asc echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list sudo apt-get update sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp cmake make - name: Setup Intel oneAPI environment shell: bash run: | source /opt/intel/oneapi/setvars.sh # Export Intel environment to GITHUB_ENV echo "CXX=icpx" >> $GITHUB_ENV echo "CC=icx" >> $GITHUB_ENV echo "PATH=$PATH" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV echo "LIBRARY_PATH=$LIBRARY_PATH" >> $GITHUB_ENV echo "CPATH=$CPATH" >> $GITHUB_ENV echo "ONEAPI_ROOT=$ONEAPI_ROOT" >> $GITHUB_ENV - name: Verify compiler run: | echo "CXX=$CXX" $CXX --version - name: Prepare build directory run: mkdir -p ${{ runner.workspace }}/build - name: Configure shell: bash env: CXX: icpx run: | cd ${{ runner.workspace }}/build cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DQUILL_BUILD_TESTS=${{ matrix.with_tests }} -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build run: | cd ${{ runner.workspace }}/build cmake --build . --config ${{ matrix.build_type }} --parallel $(nproc) - name: Test env: CTEST_OUTPUT_ON_FAILURE: True run: | cd ${{ runner.workspace }}/build ctest --build-config ${{ matrix.build_type }} --parallel $(nproc) --output-on-failure quill-12.1.0/.github/workflows/macos.yml000066400000000000000000000025661522564103500201570ustar00rootroot00000000000000name: macOS concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: build: runs-on: ${{ matrix.os }} timeout-minutes: 60 strategy: matrix: os: [ macos-14 ] build_type: [ Debug, Release ] std: [ 17, 20 ] steps: - uses: actions/checkout@v5 - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build - name: Configure working-directory: ${{runner.workspace}}/build run: | cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} -DQUILL_BUILD_TESTS=ON \ -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build working-directory: ${{runner.workspace}}/build run: | threads=`sysctl -n hw.logicalcpu` cmake --build . --config ${{matrix.build_type}} --parallel $threads - name: Test working-directory: ${{runner.workspace}}/build run: | threads=`sysctl -n hw.logicalcpu` ctest --build-config ${{matrix.build_type}} --parallel $threads --output-on-failure quill-12.1.0/.github/workflows/ubuntu.yml000066400000000000000000000121531522564103500203700ustar00rootroot00000000000000name: Ubuntu concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: build: runs-on: ${{ matrix.os }} timeout-minutes: 60 strategy: fail-fast: false matrix: cxx: [ g++-8, g++-10 ] build_type: [ Debug, Release ] std: [ 17 ] os: [ ubuntu-22.04 ] with_tests: [ ON ] include: # Build and with g++8 - cxx: g++-8 std: 17 os: ubuntu-22.04 with_tests: ON install: | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu focal main universe" sudo apt update sudo apt -o Acquire::Retries=5 install g++-8 - cxx: g++-13 build_type: Release std: 23 os: ubuntu-22.04 with_tests: ON install: sudo apt -o Acquire::Retries=5 install g++-13 - cxx: g++-13 build_type: Debug std: 23 os: ubuntu-22.04 with_tests: ON install: sudo apt -o Acquire::Retries=5 install g++-13 - cxx: g++-14 build_type: Release std: 23 os: ubuntu-24.04 with_tests: ON cmake_options: -DQUILL_ENABLE_GCC_HARDENING=ON install: sudo apt -o Acquire::Retries=5 install g++-14 - cxx: g++-14 build_type: Debug std: 23 os: ubuntu-24.04 with_tests: ON cmake_options: -DQUILL_ENABLE_GCC_HARDENING=ON install: sudo apt -o Acquire::Retries=5 install g++-14 # Builds and tests with no exceptions - cxx: g++-10 build_type: Release std: 17 os: ubuntu-22.04 with_tests: ON cmake_options: -DQUILL_NO_EXCEPTIONS=ON # Build and test with valgrind - cxx: g++-10 build_type: Release std: 20 os: ubuntu-22.04 with_tests: ON cmake_options: -DQUILL_USE_VALGRIND=ON ctest_options: -T memcheck install: sudo apt -o Acquire::Retries=5 install valgrind # Build and test address sanitizers - cxx: clang++-14 build_type: Release std: 20 os: ubuntu-22.04 with_tests: ON cmake_options: -DQUILL_SANITIZE_ADDRESS=ON # Build and test thread sanitizers - cxx: clang++-14 build_type: Release std: 20 os: ubuntu-22.04 with_tests: ON cmake_options: -DQUILL_SANITIZE_THREAD=ON # Build with clang-21 and ASAN/UBSAN (Release) - cxx: clang++-21 build_type: Release std: 23 os: ubuntu-22.04 with_tests: ON cmake_options: -DQUILL_SANITIZE_ADDRESS=ON install: | wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-21 main" sudo apt-get update for i in {1..3}; do sudo apt-get -o Acquire::Retries=3 install -y clang-21 libc++-21-dev libc++abi-21-dev && break || sleep 15 done steps: - uses: actions/checkout@v5 - name: Add repositories for newer GCC run: | sudo apt-add-repository ppa:ubuntu-toolchain-r/test if: ${{ matrix.cxx == 'g++-13' }} - name: Create Build Environment run: | sudo apt-get update ${{matrix.install}} if [[ "${{matrix.cxx}}" == "clang++-21" ]]; then sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-21 100 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-21 100 fi cmake -E make_directory ${{runner.workspace}}/build - name: Configure working-directory: ${{runner.workspace}}/build env: CXX: ${{matrix.cxx}} CXXFLAGS: ${{matrix.cxxflags}} run: | cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} ${{matrix.cmake_options}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} -DQUILL_BUILD_TESTS=${{matrix.with_tests}} \ -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build working-directory: ${{runner.workspace}}/build run: | threads=`nproc` cmake --build . --config ${{matrix.build_type}} --parallel $threads - name: Test working-directory: ${{runner.workspace}}/build run: | threads=`nproc` ctest --build-config ${{matrix.build_type}} ${{matrix.ctest_options}} --parallel $threads --output-on-failure env: CTEST_OUTPUT_ON_FAILURE: True quill-12.1.0/.github/workflows/windows.yml000066400000000000000000000060421522564103500205400ustar00rootroot00000000000000name: Windows concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' pull_request: branches: - master paths-ignore: - '**.md' - 'docs/**' - 'scripts/**' jobs: msvc: # windows-2016 and windows-2019 have MSVC 2017 and 2019 installed # respectively: https://github.com/actions/virtual-environments. runs-on: ${{ matrix.os }} timeout-minutes: 60 strategy: matrix: os: [ windows-2022 ] platform: [ x64 ] build_type: [ Debug, Release ] std: [ 17, 20 ] with_tests: [ ON ] include: # Builds the examples with no exceptions - os: windows-2022 platform: x64 build_type: Release std: 17 with_tests: "OFF" cmake_options: -DQUILL_NO_EXCEPTIONS=ON -DQUILL_BUILD_TESTS=ON # Builds for ARM - os: windows-2022 platform: ARM64 build_type: Release std: 17 with_tests: "OFF" steps: - uses: actions/checkout@v5 - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build - name: Configure shell: bash # Use a bash shell for $GITHUB_WORKSPACE. working-directory: ${{runner.workspace}}/build run: | cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} ${{matrix.cmake_options}} \ -A ${{matrix.platform}} -DCMAKE_CXX_STANDARD=${{matrix.std}} -DQUILL_BUILD_TESTS=${{matrix.with_tests}} \ -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON $GITHUB_WORKSPACE - name: Build working-directory: ${{runner.workspace}}/build run: | $threads = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors cmake --build . --config ${{matrix.build_type}} --parallel $threads - name: Test working-directory: ${{runner.workspace}}/build run: | $threads = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors ctest --build-config ${{matrix.build_type}} --parallel $threads --output-on-failure mingw: runs-on: windows-2022 timeout-minutes: 60 defaults: run: shell: msys2 {0} strategy: matrix: sys: [mingw64, ucrt64] build_type: [Release] std: [17] with_tests: [ ON ] steps: - uses: msys2/setup-msys2@v2 with: release: false msystem: ${{matrix.sys}} pacboy: cc:p cmake:p ninja:p - uses: actions/checkout@v5 - name: Configure run: cmake -B ../build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.std}} -DQUILL_BUILD_TESTS=${{matrix.with_tests}} -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON - name: Build run: cmake --build ../build # - name: Test # run: ctest --test-dir ../build --output-on-failure quill-12.1.0/.gitignore000066400000000000000000000004121522564103500147110ustar00rootroot00000000000000# Project exclude paths /cmake-build-debug/ /cmake-build-release/ /.vs /.idea /out/build/x64-Debug /CMakeSettings.json /out/build/x64-Release /out/build/Mingw64-Debug /out/build/x64-Debug-2 /docs/.tools/ /docs/Doxyfile /docs/Doxyfile.rtd /docs/build/ /docs/_build*/ quill-12.1.0/.readthedocs.yaml000066400000000000000000000011711522564103500161530ustar00rootroot00000000000000# .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-24.04 tools: python: "3.13" jobs: pre_build: - python docs/build_doxygen.py # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py # We recommend specifying your dependencies to enable reproducible builds: # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html python: install: - requirements: docs/requirements.txt quill-12.1.0/BUILD.bazel000066400000000000000000000011551522564103500146040ustar00rootroot00000000000000package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # MIT cc_library( name = "quill", hdrs = glob(["include/**/*.h"]), copts = select({ "@rules_cc//cc/compiler:gcc": ["-Wno-gnu-zero-variadic-macro-arguments"], "@rules_cc//cc/compiler:clang": ["-Wno-gnu-zero-variadic-macro-arguments"], "//conditions:default": [], }), includes = ["include"], linkopts = select({ "@platforms//os:windows": [], "@platforms//os:linux": [ "-lpthread", "-lrt", ], "//conditions:default": ["-lpthread"], }), ) quill-12.1.0/CHANGELOG.md000066400000000000000000004003021522564103500145340ustar00rootroot00000000000000- [v12.1.0](#v1210) - [v12.0.0](#v1200) - [v11.1.0](#v1110) - [v11.0.2](#v1102) - [v11.0.1](#v1101) - [v11.0.0](#v1100) - [v10.2.0](#v1020) - [v10.1.0](#v1010) - [v10.0.1](#v1001) - [v10.0.0](#v1000) - [v9.0.3](#v903) - [v9.0.2](#v902) - [v9.0.1](#v901) - [v9.0.0](#v900) - [v8.2.0](#v820) - [v8.1.1](#v811) - [v8.1.0](#v810) - [v8.0.0](#v800) - [v7.5.0](#v750) - [v7.4.0](#v740) - [v7.3.0](#v730) - [v7.2.2](#v722) - [v7.2.1](#v721) - [v7.2.0](#v720) - [v7.1.0](#v710) - [v7.0.0](#v700) - [v6.1.2](#v612) - [v6.1.1](#v611) - [v6.1.0](#v610) - [v6.0.0](#v600) - [v5.1.0](#v510) - [v5.0.0](#v500) - [v4.5.0](#v450) - [v4.4.1](#v441) - [v4.4.0](#v440) - [v4.3.0](#v430) - [v4.2.1](#v421) - [v4.2.0](#v420) - [v4.1.0](#v410) - [v4.0.0](#v400) - [v3.9.0](#v390) - [v3.8.0](#v380) - [v3.7.0](#v370) - [v3.6.0](#v360) - [v3.5.1](#v351) - [v3.5.0](#v350) - [v3.4.1](#v341) - [v3.4.0](#v340) - [v3.3.1](#v331) - [v3.3.0](#v330) - [v3.2.0](#v320) - [v3.1.0](#v310) - [v3.0.2](#v302) - [v3.0.1](#v301) - [v3.0.0](#v300) - [v2.9.2](#v292) - [v2.9.1](#v291) - [v2.9.0](#v290) - [v2.8.0](#v280) - [v2.7.0](#v270) - [v2.6.0](#v260) - [v2.5.1](#v251) - [v2.5.0](#v250) - [v2.4.2](#v242) - [v2.4.1](#v241) - [v2.4.0](#v240) - [v2.3.4](#v234) - [v2.3.3](#v233) - [v2.3.2](#v232) - [v2.3.1](#v231) - [v2.3.0](#v230) - [v2.2.0](#v220) - [v2.1.0](#v210) - [v2.0.2](#v202) - [v2.0.1](#v201) - [v2.0.0](#v200) - [v1.7.3](#v173) - [v1.7.2](#v172) - [v1.7.1](#v171) - [v1.7.0](#v170) - [v1.6.3](#v163) - [v1.6.2](#v162) - [v1.6.1](#v161) - [v1.6.0](#v160) - [v1.5.2](#v152) - [v1.5.1](#v151) - [v1.5.0](#v150) - [v1.4.1](#v141) - [v1.4.0](#v140) - [v1.3.3](#v133) - [v1.3.2](#v132) - [v1.3.1](#v131) - [v1.3.0](#v130) - [v1.2.3](#v123) - [v1.2.2](#v122) - [v1.2.1](#v121) - [v1.2.0](#v120) - [v1.1.0](#v110) - [v1.0.0](#v100) ## v12.1.0 - Updated bundled `libfmt` to `v12.2.0`. - Fixed append-mode `RotatingFileSink` recovery for base filenames without an extension, so `DateAndTime` rotated files such as `application.20260622_120000` are counted towards `max_backup_files` instead of accumulating across restarts. ([#938](https://github.com/odygrd/quill/discussions/938)) - Fixed Windows builds that include `` before Quill wide-string logging headers. ([#941](https://github.com/odygrd/quill/issues/941)) - Fixed size-based `RotatingFileSink` rotation after an externally deleted active file is reopened. ([#945](https://github.com/odygrd/quill/pull/945)) - Fixed bounded queue writes after the reader drains the queue without crossing the reader-position publish batch. ([#946](https://github.com/odygrd/quill/pull/946)) - Fixed `%s` timestamp formatting in `GmtTime` mode on non-UTC machines. ([#947](https://github.com/odygrd/quill/pull/947)) - Fixed a huge page mapping leak on Linux where `munmap` failed with `EINVAL` on queue destruction. Allocations now request `MAP_HUGE_2MB` explicitly and round the mapping size up to a 2 MiB multiple. - Fixed the transit event buffer expanding to twice the configured `transit_events_hard_limit`. - `Backend::start()` now throws on the caller thread when `transit_events_soft_limit` or `transit_events_hard_limit` is misconfigured, instead of terminating the process from the backend thread. - Fixed `BackendTscClock` calls overlapping `Backend::stop()`. Backend restarts now reconfigure and republish one stable clock allocation, so a conversion already in progress can safely finish without unbounded retained clocks. - Fixed potential queue corruption when logging `std::error_code` with locale-dependent or user-provided error categories. The category name and message are now snapshotted once and reused for encoding. - Fixed `RotatingJsonFileSink` replaying a stale json payload after a failed size-based rotation. - Literal `{` and `}` in `format_pattern` are now escaped, while existing doubled-brace spelling remains compatible. Invalid attribute format specifications are rejected during formatter construction. - `timestamp_pattern` now rejects the time-of-day-embedding modifiers `%c`, `%Ec`, `%EX`, `%OH`, `%OI`, `%OM` and `%OS`, like `%X`, which silently froze at a cached value. - Fixed logging of `std::pair`, `std::tuple` and `std::array` with const-qualified element types, most notably dereferenced `std::map` iterators (`std::pair`), which previously failed to compile. - The backend singleton lock file is now opened with `O_CLOEXEC` and `O_NOFOLLOW`. - The `std::filesystem::path` codec now reads the path via `native()`, avoiding two temporary string allocations on the hot path. - `Codec` now fails with a clear `static_assert` when the decoded tuple is not formattable. A custom formatter for the complete tuple remains supported even when elements have no standalone formatter. - `TransitEventBuffer` expansion now moves the existing events instead of default-constructing and discarding a `FormatBuffer` allocation for every slot. - Fixed a C++ data race in `BackendTscClock` snapshot reads when resynchronization reused a slot concurrently. - Fixed SIGTERM and SIGINT handling when the backend is running without a valid logger. - Unbounded queue maximum capacities are now rounded up to the next power of two and validated against the initial capacity. - Sink exceptions no longer prevent later sinks from receiving the same log or metric event. - Logging macros now evaluate logger and runtime log-level expressions once per invocation. - CPU-affinity failures are now reported on macOS, FreeBSD, and NetBSD instead of being silently ignored. - Minutely and hourly rotation boundaries now stay wall-clock aligned after a late-triggered rotation, instead of permanently drifting off the initial rotation time point. - Fixed a number of minor bugs and hardened edge cases across the frontend, backend, sinks and codecs, including transactional startup rotation recovery and console colour handling around trailing newlines. - Clarified the custom-codec exception contract: sizing may throw before reservation, while encoding and decoding must not. - Documented the `QUILL_LOG_LEVEL` environment variable. It is now validated during first logger creation; invalid values (including `backtrace`) throw `QuillError`, do not register a partial logger, and can be retried. - `create_or_get_sink()` now throws when a sink with the same name already exists with an incompatible type (in builds with RTTI), instead of returning it for an undefined-behaviour cast. - Documented that `CsvWriter` writes fields verbatim and added an opt-in `quill::utility::csv_escape_field()` helper for RFC 4180 escaping of fields containing commas, quotes or line breaks. - Backend callback logging no longer self-deadlocks when its own blocking queue is full; additional backend-thread records are dropped instead. - Exceptions from custom sink periodic tasks are now reported through `error_notifier` instead of terminating the process. - Concurrent `Backend::stop()` callers now wait for the in-progress shutdown to complete before returning. - Default JSON sinks now suffix named arguments that collide with built-in JSON fields, avoiding duplicate object keys. - Oversized runtime source paths are now truncated safely instead of overflowing metadata offsets. - Negative backend and file-sync intervals are now rejected during configuration. - Fixed Windows `std::filesystem::path` decoding when byte-packed arguments are not aligned for `wchar_t`. - Fixed rotating `CsvWriter` header writes on Windows after failed rotation recovery, so the header is appended instead of overwriting the beginning of the active CSV file. ## v12.0.0 This release introduces asynchronous metrics, broadens codec coverage, and adds API and reliability improvements across backend lifecycle handling, sinks, and platform-specific paths. Quill can now offload both logs and metric samples through the same backend worker, with metric metadata registered up front and each publish call enqueueing only a compact, fixed-size sample record on the hot path. - Added asynchronous metrics support, including metric registration APIs, `Logger::publish_metric()`, the `METRIC(...)` macro, and backend sink delivery through `Sink::write_metric()`. - Added an optional `PrometheusSink` and examples for both a custom metric sink and Prometheus-backed export: [custom metric sink example](https://github.com/odygrd/quill/blob/master/docs/snippets/quill_docs_example_metric_publishing.cpp), [Prometheus sink example](https://github.com/odygrd/quill/blob/master/examples/metric_publishing_prometheus.cpp) - Added per-thread mapped diagnostic context (MDC) support with `Logger::set_mdc()`, `Logger::erase_mdc()`, `Logger::clear_mdc()`, the `%(mdc)` pattern attribute, and `BackendOptions::mdc_format_pattern` for global MDC rendering. - Added std codec support for `std::variant`, `std::bitset`, `std::complex`, and `std::error_code`. - Extended `quill/std/Chrono.h` codec support to match bundled fmt's C++20 calendar formatters, including `std::chrono::year`, `month`, `day`, `weekday`, and `year_month_day` when available. - Added C++20 module support groundwork, including export markers and macro cleanup. - Switched to native file handles (`CreateFile`/`WriteFile`) on Windows for improved write throughput compared to `FILE*`. - Added strict `Frontend::create_sink()` and `Frontend::create_logger()` APIs for callers that want duplicate names to fail instead of reusing existing objects. - Added `CsvWriter::close()` for deterministic logger removal and file closure before backend shutdown. - Added `BackendOptions::ensure_monotonic_output_timestamps` to correct regular log and metric output timestamps that would otherwise move backwards. Backtrace records keep their original capture timestamps. - `BackendOptions::cpu_affinity` now supports pinning the backend to multiple CPUs. - Added a fallback to `fs::absolute` when `fs::canonical` fails on RAM disks. ([#910](https://github.com/odygrd/quill/issues/910)) - Hardened backend, signal-handler, manual-backend, and teardown paths with more robust startup and shutdown behavior. - Fixed multiple codec, sink rotation, named-argument, queue, and platform-specific edge cases. - Fixed an infinite loop in the backend when the user-provided `error_notifier` throws. ([#915](https://github.com/odygrd/quill/issues/915)) - Generated a Doxygen tag file for downstream documentation linking. ([#914](https://github.com/odygrd/quill/issues/914)) - Fix rotating sink reopen failure when the disk is full ([#919](https://github.com/odygrd/quill/issues/919)) - Fixes DLL unload on Windows, drain remaining log messages in stop() when backend thread was terminated externally ([#925](https://github.com/odygrd/quill/discussions/925)) - Fixed stale named arguments from a pooled `TransitEvent`. The `named_args` pointer is now consistently `nullptr` for log statements without named arguments instead of occasionally being an empty vector ([#926](https://github.com/odygrd/quill/issues/926)) - `StopWatch` now samples its elapsed time on the frontend at the log call site instead of when the backend formats the message, so logged values no longer include backend latency. - `RotatingFileSink` in append mode now counts rotated files left behind by previous runs towards `max_backup_files` for all `RotationNamingScheme` values, removing the oldest files on startup when they exceed the limit instead of letting them accumulate across restarts. Previously only the `Index` scheme (and the `Date` scheme for same-day files) recovered existing files, so `Date` and `DateAndTime` files from earlier runs were never cleaned up. Recovered append-mode files are not removed when `overwrite_rolled_files` is set to `false`. ([#930](https://github.com/odygrd/quill/discussions/930)) ## v11.1.0 - Fixed thread-local context duplication across shared libraries ([#890](https://github.com/odygrd/quill/issues/890)) - Added a `nullptr` check in macro-free log functions (`LogFunctions.h`) to allow calls with an uninitialized logger. Macro-based logging remains deliberately unchanged ([#894](https://github.com/odygrd/quill/issues/894)) - Suppress GCC false-positive warnings during LTO builds. - Added backend worker poll loop hooks `backend_worker_on_poll_begin`/ `backend_worker_on_poll_end` ([#897](https://github.com/odygrd/quill/issues/897)) - Added opt-in sequential thread IDs via `QUILL_USE_SEQUENTIAL_THREAD_ID` with `QUILL_DEFINE_SEQUENTIAL_THREAD_ID` ([#898](https://github.com/odygrd/quill/issues/898)) ## v11.0.2 - Fixed UBSAN warning when logging empty `std::string_view` ([#885](https://github.com/odygrd/quill/issues/885)) - Updated `ConsoleSink` constructor to accept an optional `FileEventNotifier` parameter for consistency with other sinks ([#886](https://github.com/odygrd/quill/issues/886)) ## v11.0.1 - Fix `BacktraceStorage` `index` reset to prevent `SIGSEGV` when using `LOG_BACKTRACE` ## v11.0.0 - Update bundled `libfmt` to `v12.1.0` - Minor correction to `_last_sink_flush_time update` when `fflush()` fails - Added retry logic and shared access handling for file open and rotation on Windows - Use `::WriteFile` instead of `fwrite` to prevent `\r\r\n` line endings on Windows - Avoid file descriptor leaks by setting `O_CLOEXEC` on Unix and `HANDLE_FLAG_INHERIT` on Windows - Added `SimpleSetup.h` convenience header for trivial program cases to easily setup a logger. For example ```c++ #include "quill/SimpleSetup.h" #include "quill/LogMacros.h" int main() { auto* logger = quill::simple_logger(); LOG_INFO(logger, "Hello from {}!", "Quill"); auto* logger2 = quill::simple_logger("test.log"); LOG_INFO(logger2, "This message goes to a file"); } ``` - Fixed argument forwarding when encoding user-defined types with `DeferredFormatCodec` or STL containers to properly handle rvalue references. For example, the following move-only type will now work correctly: ```c++ class MoveOnlyType { public: MoveOnlyType(std::string name, std::string value, uint32_t count) : name(std::move(name)), value(std::move(value)), count(count) {} MoveOnlyType(MoveOnlyType&&) = default; MoveOnlyType(MoveOnlyType const&) = delete; std::string name; std::string value; uint32_t count; }; template <> struct fmtquill::formatter { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } auto format(MoveOnlyType const& obj, format_context& ctx) const { return fmtquill::format_to(ctx.out(), "MoveOnlyType(name: {}, value: {}, count: {})", obj.name, obj.value, obj.count); } }; template <> struct quill::Codec : quill::DeferredFormatCodec {}; MoveOnlyType obj{"Test", "Value1", 42}; LOG_INFO(logger, "obj: {}", std::move(obj)); // Properly forwards and moves ``` ## v10.2.0 - Added fuzzing tests to CI to catch memory and undefined behavior issues - Fixed `PatternFormatter` automatic newline appending by making the suffix ('\n') configurable or optionally disabled via `PatternFormatterOptions` - Fixed segmentation fault when `DirectFormatCodec` was used with enums types ([#848](https://github.com/odygrd/quill/issues/848)) - Fixed segmentation fault when `DirectFormatCodec` was used with STL containers of enums - Fixed a compiler error when `LOG_DYNAMIC` is used with `QUILL_DISABLE_FILE_INFO` ([#847](https://github.com/odygrd/quill/issues/847)) - Fixed process ID capture in `BackendWorker` to support `fork()` correctly ([#860](https://github.com/odygrd/quill/issues/860)) - Fixed undefined behavior caused by passing `nullptr` to `memcpy` when encoding empty `std::vector` - Updated `BackendOptions::check_printable_char` to allow tab (`\t`) and carriage return (`\r`) characters by default ([#856](https://github.com/odygrd/quill/issues/856)) - Increased `RdtscClock` resync lag thresholds to improve cross-system compatibility - Added `QUILL_ENABLE_ASSERTIONS` CMake option and preprocessor flag to enable assertions in release builds - Allow `RotatingSink` to rotate the file on creation with `rotation_on_creation()` - Improved `SignalHandlerOptions` configurability by replacing hardcoded logger exclusion string with `excluded_logger_substrings` option - Silence MSVC warnings (4324, 4996) in source code instead of CMake ## v10.1.0 - Fixed potential conflicts by adding unique prefixes to internal macro variables to prevent conflicts with user variable names in the same scope. ([#799](https://github.com/odygrd/quill/issues/799)) - Fixed potential `UBSan` warnings by adding overflow check when doubling resync interval in `RdtscClock::resync()` ([#809](https://github.com/odygrd/quill/issues/809)) - Minor improvements in `Utility::to_hex` function and `StringFromTime` - Fixed an issue where `BackendWorker::_exit` was always executed during destruction, even when the backend thread had already stopped ([#815](https://github.com/odygrd/quill/issues/815)) - Fixed `RotatingFileSink` to correctly handle `FilenameAppendOption::StartDate` configuration ([#822](https://github.com/odygrd/quill/issues/822)) - Fixed unnecessary allocation caused by empty `std::vector` while `BackendWorker` is idle on Windows ([#827](https://github.com/odygrd/quill/issues/827)) - Fixed `FileSink::open_mode` string comparison for file mode flags - Adjusted default `BackendOptions` values for broader system compatibility and typical usage patterns ## v10.0.1 - Fixed PatternFormatter test to work with any repository name instead of hardcoded `quill` ([#795](https://github.com/odygrd/quill/issues/795)) - Fixed Windows compiler warnings when clang-cl >= 19 is used ## v10.0.0 ### New Features - There is a new macro-free mode that allows logging without macros. You have two options: either `#include "quill/LogMacros.h"` or `#include "quill/LogFunctions.h"`. The macro mode still remains the recommended and main method for logging. The new macro-free log has higher overhead than using macros. To use the macro-free mode, for example: ```cpp quill::debug(logger, "A {} message with number {}", "test", 123); ``` See macro-free mode documentation [here](https://quillcpp.readthedocs.io/en/latest/macro_free_mode.html) for details. - Added `BinaryDataDeferredFormatCodec` for efficient binary data logging. This codec allows efficient logging of variable-sized binary data by copying the raw bytes on the hot path and deferring the formatting to the backend thread. This is particularly useful for logging binary protocol messages (like SBE or custom binary formats), network packets, and raw binary data without impacting application performance. See the example [sbe_logging](https://github.com/odygrd/quill/blob/master/examples/sbe_binary_data/sbe_logging.cpp) and [binary_protocol_logging](https://github.com/odygrd/quill/blob/master/examples/binary_protocol_logging.cpp) for details. For documentation, see [here](https://quillcpp.readthedocs.io/en/latest/binary_protocols.html). - The immediate flush feature has been enhanced to support interval-based flushing and moved to runtime. This feature helps with debugging by ensuring log statements are flushed to the sink, blocking the caller thread. ([#660](https://github.com/odygrd/quill/issues/660)) - Added `source_location_path_strip_prefix` option in `PatternFormatterOptions` to customize the display of the `%(source_location)` attribute of `PatternFormatter`. When set, any paths that contain this prefix will have the prefix and everything before it stripped from the displayed path. For example, with prefix "projects", a source location like "/home/user/projects/app/main.cpp:5" would be displayed as "app/main.cpp: 5". ([#772](https://github.com/odygrd/quill/issues/772)) - Added `source_location_remove_relative_paths` option in `PatternFormatterOptions` to remove relative path components from the `%(source_location)` attribute of `PatternFormatter`. When enabled, relative path components like "../" are processed and removed, simplifying paths from `__FILE__` which might contain relative paths like "../../../test/main.cpp". ([#778](https://github.com/odygrd/quill/issues/778)) - Added the `QUILL_DISABLE_FILE_INFO` preprocessor flag and CMake option. This disables `__FILE__` and `__LINE__` information in log statements at compile time when location-related patterns (`%(file_name)`, `%(line_number)`, `%(short_source_location)`, `%(source_location)`) are not needed in the `PatternFormatter`. This removes embedded source path strings from built binaries from the security viewpoint. - Added the `QUILL_DETAILED_FUNCTION_NAME` CMake option. When enabled, this option uses compiler-specific detailed function signatures (such as `__PRETTY_FUNCTION__` on GCC/Clang or `__FUNCSIG__` on MSVC) instead of the standard `__FUNCTION__` in log macros. This provides more complete function information, including return types, namespaces, and parameter types. This option is only relevant when `%(caller_function)` is used in the pattern formatter. ([#785](https://github.com/odygrd/quill/issues/785)) - Added `process_function_name` customisation point in `PatternFormatterOptions`. This function allows custom processing of the function signature before it's displayed in logs. This makes more sense to use when `QUILL_DETAILED_FUNCTION_NAME` is used. This provides flexibility to trim, format, or otherwise modify function signatures to improve readability in log output when using the `%(caller_function)` pattern. ([#785](https://github.com/odygrd/quill/issues/785)) - Added helper macros for easy logging of user-defined types. Two new macros are available in `quill/HelperMacros.h`: - `QUILL_LOGGABLE_DIRECT_FORMAT(Type)`: For types that contain pointers or have lifetime dependencies - `QUILL_LOGGABLE_DEFERRED_FORMAT(Type)`: For types that only contain value types and are safe to copy Note that these macros require you to provide either an `operator<<` for your type and they are just shortcuts to existing functionality. ([#777](https://github.com/odygrd/quill/issues/777)) Example usage: ```cpp class User { /* ... */ }; std::ostream& operator<<(std::ostream& os, User const& user) { /* ... */ } // For types with pointers - will format immediately QUILL_LOGGABLE_DIRECT_FORMAT(User) class Product { /* ... */ }; std::ostream& operator<<(std::ostream& os, Product const& product) { /* ... */ } // For types with only value members - can format asynchronously QUILL_LOGGABLE_DEFERRED_FORMAT(Product) ``` ### Improvements - Internally, refactored how runtime metadata are handled for more flexibility, providing three macros for logging with runtime metadata: - `QUILL_LOG_RUNTIME_METADATA_DEEP` - Takes a deep copy of `fmt`, `file`, `function` and `tags`. Most flexible option, useful for forwarding logs from another logging library. - `QUILL_LOG_RUNTIME_METADATA_HYBRID` - Will take a deep copy of `fmt` and `tags` and will take `file` and `function` as reference. This is used for the new macro-free mode. - `QUILL_LOG_RUNTIME_METADATA_SHALLOW` - Will take everything as reference. This is used when logging with compile-time metadata and using, for example, a dynamic log-level such as `LOG_DYNAMIC`. - When using a sink with overridden `PatternFormatterOptions`, the option `add_metadata_to_multi_line_logs` will now be correctly applied at the Sink level. Previously, this option was only available and effective at the Logger level `PatternFormatter`. - When a Sink with override `PatternFormatterOptions` is used and if no other sink exists using the `Logger` `PatternFormatterOptions`, then the backend thread will no longer perform a redundant format log statement. - When using a sink with overridden `PatternFormatterOptions`, the `log_statement` that is passed to the `Filter::filter()` will now be formatted based on the overridden options instead of using the `Logger` `PatternFormatterOptions`. - Update bundled `libfmt` to `v11.2.0` ### API Changes - If you were previously setting `QUILL_ENABLE_IMMEDIATE_FLUSH` to `1`, this functionality has been moved to runtime with more flexibility. Instead of using a boolean flag, you can now specify the flush interval by calling `logger->set_immediate_flush(flush_every_n_messages)` on each logger instance. Set it to `1` for per-message flushing, or to a higher value to flush after that many messages. Setting it to `0` disables flushing which is the default behaviour. `QUILL_ENABLE_IMMEDIATE_FLUSH` still exists as a compile-time preprocessor flag and is set to `1` by default. Setting `QUILL_ENABLE_IMMEDIATE_FLUSH 0` in the preprocessor will eliminate the `if` branch from the hot path and disable this feature entirely, regardless of the value passed to `set_immediate_flush(flush_every_n_messages)`. - The `QUILL_LOG_RUNTIME_METADATA` macro requires `file`, `function` and `fmt` to be passed as `char const*` and `line_number` as `uint32_t`. This is a breaking change from the previous version. ## v9.0.3 - Add support for `void*` formatting ([#759](https://github.com/odygrd/quill/issues/759)) - Fix a bug in `RotatingJsonFileSink.h` where file size-based rotation wasn't triggering properly ([#767](https://github.com/odygrd/quill/issues/767)) - Fix false positive `-Wstringop-overread` warning in GCC ([#766](https://github.com/odygrd/quill/issues/766)) ## v9.0.2 - Add missing namespace in `QUILL_LOG_RUNTIME_METADATA` ([#743](https://github.com/odygrd/quill/issues/743)) ## v9.0.1 - Fix crash when `LOG_BACKTRACE` is used ([#744](https://github.com/odygrd/quill/issues/744)) - Add missing namespace in `QUILL_LOG_RUNTIME_METADATA` ([#743](https://github.com/odygrd/quill/issues/743)) - Check for `nullptr` `Logger*` before setting log level via `QUILL_LOG_LEVEL` environment variable ([#749](https://github.com/odygrd/quill/issues/749)) - Change default mode of `FileSink` `fopen` to `a` to avoid overwriting existing files ## v9.0.0 ### API Changes - Replaced the `bool huge_pages_enabled` flag in `FrontendOptions` with `quill::HugePagesPolicy huge_pages_policy` enum, allowing huge page allocation to be attempted with a fallback to normal pages if unavailable. If you are using a custom `FrontendOptions` type, you will need to update it to use the new flag. ([#707](https://github.com/odygrd/quill/issues/707)) - Previously, `QueueType::UnboundedDropping` and `QueueType::UnboundedBlocking` could grow up to 2 GB in size. This limit is now configurable via `FrontendOptions::unbounded_queue_max_capacity`, which defaults to 2 GB. - `QueueType::UnboundedUnlimited` has been removed, as the same behavior can now be achieved by setting `FrontendOptions::unbounded_queue_max_capacity` to the maximum value. - The `ConsoleSink` constructor now optionally accepts a `ConsoleSinkConfig`, similar to other sinks. If no `ConsoleSinkConfig` is provided, a default one is used, logging to `stdout` with `ColourMode::Automatic`. For example: ```c++ Frontend::create_or_get_sink("console_sink", []() { ConsoleSinkConfig config; config.set_colour_mode(ConsoleSinkConfig::ColourMode::Never); config.set_stream("stderr"); return config; }()); ``` ### New Features - The default log level for each `Logger` can now be configured using the environment variable `QUILL_LOG_LEVEL`. Supported values: `"tracel3"`, `"tracel2"`, `"tracel1"`, `"debug"`, `"info"`, `"notice"`, `"warning"`, `"error"`, `"critical"`, `"none"`. When set, the logger is initialized with the corresponding log level. If `logger->set_log_level(level)` is explicitly called in code, it will override the log level set via the environment variable. - Added the `LOG_RUNTIME_METADATA(logger, log_level, file, line_number, function, fmt, ...)` macro. This enables passing runtime metadata (such as file, line number, and function) along with a log message, providing greater flexibility when forwarding logs from other logging libraries. ([#696](https://github.com/odygrd/quill/issues/696)) ```c++ LOG_RUNTIME_METADATA(logger, quill::LogLevel::Info, "main.cpp", 20, "foo()", "Hello number {}", 8); ``` - Added a runtime check to detect duplicate backend worker threads caused by inconsistent linkage (e.g., mixing static and shared libraries). If needed, this check can be disabled using the `check_backend_singleton_instance` flag in `BackendOptions`. ([#687](https://github.com/odygrd/quill/discussions/687#discussioncomment-12349621)) - Added the `QUILL_DISABLE_FUNCTION_NAME` preprocessor flag and CMake option. This allows disabling `__FUNCTION__` in `LOG_*` macros when `%(caller_function)` is not used in `PatternFormatter`, eliminating Clang-Tidy warnings when logging inside lambdas. - It is now possible to override a logger's `PatternFormatter` on a per-sink basis. This allows the same logger to output different formats for different sinks. Previously, achieving this required creating a custom sink type, but this functionality is now built-in. See the example: [sink_formatter_override](https://github.com/odygrd/quill/blob/master/examples/sink_formatter_override.cpp). - Added `Frontend::remove_logger_blocking(...)`, which blocks the caller thread until the specified logger is fully removed. - Added `Frontend::shrink_thread_local_queue(capacity)` and `Frontend::get_thread_local_queue_capacity()`. These functions allow dynamic management of thread-local SPSC queues when using an unbounded queue configuration. They enable on-demand shrinking of a queue that has grown due to bursty logging, helping to reduce memory usage, although in typical scenarios they won't be required. - Added the `SyslogSink`, which logs messages to the system's syslog. ```c++ auto sink = quill::Frontend::create_or_get_sink( "app", []() { quill::SyslogSinkConfig config; config.set_identifier("app"); return config; }()); ``` - Added the `SystemdSink`, which logs messages to systemd. ```c++ auto sink = quill::Frontend::create_or_get_sink( "app", []() { quill::SystemdSinkConfig config; config.set_identifier("app"); return config; }()); ``` - Added the `AndroidSink`, which integrates with Android's logging system. ```c++ auto sink = quill::Frontend::create_or_get_sink( "s1", []() { quill::AndroidSinkConfig config; config.set_tag("app"); config.set_format_message(true); return config; }()); ``` ### Improvements - Updated bundled `libfmt` to `11.1.4`. - When `add_metadata_to_multi_line_logs` in the `PatternFormatter` was set to false, fixed a bug where the last character of the log message was dropped and added protection for empty messages. - Updated `LOG_EVERY_N` macros to log on the first occurrence (0th call) instead of waiting until the Nth call. - Added a `nullptr` check for `char*` and `const char*` during encoding, ensuring the library handles `nullptr` values gracefully ([#735](https://github.com/odygrd/quill/discussions/735)) - The `CsvWriter` could previously be used with `RotatingFileSink` via the constructor that accepted `std::shared_ptr`, but rotated files did not include the CSV header. This has now been improved—when using the new constructor that accepts `quill::RotatingFileSinkConfig`, the CSV header is written at the start of each new rotated file. ([#700](https://github.com/odygrd/quill/discussions/700)) ```c++ quill::RotatingFileSinkConfig sink_config; sink_config.set_open_mode('w'); sink_config.set_filename_append_option(FilenameAppendOption::None); sink_config.set_rotation_max_file_size(512); sink_config.set_rotation_naming_scheme(RotatingFileSinkConfig::RotationNamingScheme::Index); quill::CsvWriter csv_writer{"orders.csv", sink_config}; for (size_t i = 0; i < 40; ++i) { csv_writer.append_row(132121122 + i, "AAPL", i, 100.1, "BUY"); } ``` - When using `CsvWriter` with `open_mode == 'a'`, the header will no longer be rewritten if the file already exists. - On Linux, setting a long backend thread name now truncates it instead of failing. ([#691](https://github.com/odygrd/quill/issues/691)) - Fixed BSD builds. ([#688](https://github.com/odygrd/quill/issues/688)) - Added adaptive termination for stable measurements in `rdtsc` calibration during init - Fixed `QUILL_ATTRIBUTE_HOT` and `QUILL_ATTRIBUTE_COLD` clang detection - CMake improvements: switched to range syntax for minimum required version and bumped minimum required CMake version to `3.12`. ([#686](https://github.com/odygrd/quill/issues/686)) - Correct the installation location of pkg-config files. They are now properly placed in `/usr/local/lib`. ([#715](https://github.com/odygrd/quill/issues/715)) - Removed deprecated `TriviallyCopyableTypeCodec` ## v8.2.0 - Added `DeferredFormatCodec` and `DirectFormatCodec` for easier logging of user-defined types and smoother migration from pre-`v4` versions. Previously, users had to define a custom `Codec` for every non-trivially copyable user-defined type they wanted to log. ```c++ template <> struct quill::Codec : quill::DeferredFormatCodec { }; template <> struct quill::Codec : quill::DirectFormatCodec { }; ``` - `DeferredFormatCodec` now supports both trivially and non-trivially copyable types: - For trivially copyable types, it behaves the same as `TriviallyCopyableTypeCodec`. - For non-trivially copyable types, it works similarly to pre-`v4` by taking a copy of the object using the copy constructor and placement new. - `DirectFormatCodec` formats the object immediately in the hot path, serving as a shortcut to explicitly formatting the object when logging. - For advanced use cases, a custom `Codec` can still be defined for finer control over encoding/decoding. See: - [DeferredFormatCodec Usage](https://github.com/odygrd/quill/blob/master/examples/user_defined_types_logging_deferred_format.cpp) - [DirectFormatCodec Usage](https://github.com/odygrd/quill/blob/master/examples/user_defined_types_logging_direct_format.cpp) - [Documentation](https://quillcpp.readthedocs.io/en/latest/cheat_sheet.html#logging-user-defined-types) - Added codec support for C-style arrays of user-defined types in `std/Array.h` - Fixed warnings: `-Wimplicit-int-float-conversion`, `-Wfloat-equal`, and `-Wdocumentation`. - Marked `TriviallyCopyableTypeCodec` as deprecated. `DeferredFormatCodec` should be used instead, requiring no further changes. - Raised minimum `CMake` required version from `3.8` to `3.10` to avoid deprecation warnings. ## v8.1.1 - Updated bazel `rules_cc` to `0.1.1` ([#664](https://github.com/odygrd/quill/issues/664)) ## v8.1.0 - Updated bundled `libfmt` to `11.1.3` - Suppressed clang-19 warning when building the tests with C++17. ([#646](https://github.com/odygrd/quill/issues/646)) - Fixed windows linkage error when shared library is used. - Fixed redefinition of `struct fmt_detail::time_zone` error ([#649](https://github.com/odygrd/quill/issues/649)) ## v8.0.0 - Unified `JsonFileSink.h` and `JsonConsoleSink.h` into a single header, `JsonSink.h`, with both classes now sharing a common implementation - Users can now inherit from `JsonFileSink` or `JsonConsoleSink` and override the `generate_json_message(...)` function to implement their own custom JSON log formats - Removed `JsonFileSinkConfig`. Please rename it to `FileSinkConfig`, which retains the same API and is fully compatible. - Added `RotatingJsonFileSink`. Functions like `RotatingFileSink`, but specifically designed for rotating JSON log files. ([#637](https://github.com/odygrd/quill/issues/637)) - Simplified `ConsoleSink` by applying ANSI colour codes universally across all platforms, including Windows. The previous Windows-specific implementation has been removed. Note that `quill::ConsoleColours` has been replaced with `quill::ConsoleSink::Colours`, and `quill::ConsoleColours::ColourMode` has been renamed to `quill::ConsoleSink::ColourMode`. - Changed class member visibility in `FileSink`, `JsonSink`, and `RotatingSink` from private to protected, enabling easier customization through inheritance for user-defined implementations. - Added a new `sink_min_flush_interval` option in `BackendOptions`, which specifies the minimum time interval (in milliseconds) before the backend thread flushes the output buffers calling `flush_sink()` for all sinks, with a default value of 200ms; The backend thread ensures sinks aren't flushed more frequently than this interval, while explicit calls to `logger->flush_log()` trigger an immediate flush, and flushing may occur less frequently if the backend thread is busy, with this setting applying globally to all sinks. Setting this value to 0 disables the feature. ([#641](https://github.com/odygrd/quill/issues/641)) - Updated bundled `libfmt` to `11.1.2` - Added a `StopWatch` utility for easy logging of elapsed time. It can log the time elapsed since construction in various formats. You can use either `quill::StopWatchTsc` for high-resolution TSC-based timing or `quill::StopWatchChrono` for standard std::chrono-based timing. ([#640](https://github.com/odygrd/quill/issues/640)) For example: ```c++ #include "quill/StopWatch.h" quill::StopWatchTsc swt; std::this_thread::sleep_for(std::chrono::seconds(1)); LOG_INFO(logger, "After 1s, elapsed: {:.6}s", swt); // => After 1s, elapsed: 1.00849s std::this_thread::sleep_for(std::chrono::milliseconds(500)); LOG_INFO(logger, "After 500ms, elapsed: {}s", swt); // => After 500ms, elapsed: 1.521880274s LOG_INFO(logger, "elapsed: {}", swt.elapsed_as()); // => elapsed: 1521807324ns ``` - Suppress `-Wredundant-decls` warning in GCC builds. - Remove `-Wno-gnu-zero-variadic-macro-arguments` for GCC in CMake. ## v7.5.0 - In previous versions, logging on Windows automatically included `windows.h` in all components. The frontend will no longer include `windows.h`. By following the recommended usage example provided [here](https://github.com/odygrd/quill/blob/master/examples/recommended_usage/recommended_usage.cpp) as guidance, you can create a wrapper library around Quill for the backend, allowing you to log on Windows without including `windows.h` in the frontend or main program. ([#618](https://github.com/odygrd/quill/issues/618)) - The `LOG_LEVEL_LIMIT` time-based rate-limiting macros now log the count of how many times a message would be logged when throttled. For example, a log message may appear as `A log message with number 123 (21x)` to indicate that the message would have been logged 21 times. ([#616](https://github.com/odygrd/quill/issues/616)) - New macros `LOG_LEVEL_LIMIT_EVERY_N` have been added, allowing for count-based rate limiting and giving developers greater control over logging frequency. ([#616](https://github.com/odygrd/quill/issues/616)) - Renamed `PACKED` used in `libfmt` to `QUILLPACKED` to avoid naming collisions. ([#620](https://github.com/odygrd/quill/issues/620)) - The `set_thread_name` function has been fixed to provide accurate error reporting, ensuring that the correct error message is displayed in the event of a failure. ## v7.4.0 - Fixed a build issue when compiling with `-fno-rtti`. This ensures compatibility with projects that disable `RTTI`. ([#604](https://github.com/odygrd/quill/issues/604)) - Fixed an incorrectly triggered assertion in debug builds when `BackendOptions::log_timestamp_ordering_grace_period` is set to 0 ([#605](https://github.com/odygrd/quill/issues/605)) - Fixed a compile-time error in `CsvWriter` that occurred when passing a custom `FrontendOptions` type as a template parameter. ([#609](https://github.com/odygrd/quill/issues/609)) - Added accessors to `Logger` for sinks, user clock source, clock source type, and pattern formatter options that can be used to create another `Logger` with similar configuration. - Added `ConsoleColours::ColourMode` to `ConsoleSink`, allowing colors to be explicitly forced or conditionally enabled based on the environment. Previously, colors were only conditionally enabled. ([#611](https://github.com/odygrd/quill/issues/611)). For example: ```cpp quill::Frontend::create_or_get_sink( "sink_id_1", quill::ConsoleColours::ColourMode::Automatic); ``` ## v7.3.0 - Added the option to explicitly specify the `Logger` used by the built-in `SignalHandler` for logging errors during application crashes. ([#590](https://github.com/odygrd/quill/issues/590)) - Prevented error logs from the `SignalHandler` from being output to CSV files when a `CsvWriter` is in use. ([#588](https://github.com/odygrd/quill/issues/588)) - Introduced `SignalHandlerOptions` to simplify and unify the API. `Backend::start_with_signal_handler` is now deprecated, replaced by a new `Backend::start` overload that accepts `SignalHandlerOptions` for enabling signal handling. - Added a new `create_or_get_logger` overload that accepts a `std::vector>`, improving flexibility by allowing a variable number of sinks to be passed at runtime when creating a logger. - Added a new overload to `create_or_get_logger` to create a logger that inherits configuration options from a specified logger. ([#596](https://github.com/odygrd/quill/issues/596)) - Implemented a workaround to resolve false positive warnings from `clang-tidy` on Windows. ## v7.2.2 - Fixed race condition during DLL unload by ensuring safe cleanup of `ThreadContext` when calling `flush_log()` ([#586](https://github.com/odygrd/quill/issues/586)) ## v7.2.1 - Fixed an unused variable warning treated as an error on MSVC. ## v7.2.0 **Bug Fixes:** - Fixed compile error in `BackendTscClock` ([#577](https://github.com/odygrd/quill/issues/577)) - Added a missing header include in `TriviallyCopyableCodec.h`. ([#560](https://github.com/odygrd/quill/issues/560)) - Fixed incorrect log level short codes introduced in v7 after adding the new log level `NOTICE`. Using `%(log_level_short_code)` in the pattern formatter could incorrectly map `LOG_ERROR` to `"C"` and LOG_WARNING to `"E"`. ([#564](https://github.com/odygrd/quill/issues/564)) - Fixed an overflow issue when logging more than `uint32_t::max()` bytes in a single log message. For example, attempting to log `std::string s(std::numeric_limits::max(), 'a');` would previously cause a crash. **Improvements:** - Optimised dynamic log level handling and size calculation for fundamental types, `std::string` and `std:: string_view` on the hot path. - Several enhancements to the backend worker thread, resulting in an overall 10% backend throughput increase. Key optimizations include the simplification of `TransitEventBuffer`, reducing the memory footprint of `TransitEvent`, introducing support for custom buffer sizes in file streams and tuning `transit_events_soft_limit` and `transit_events_hard_limit` default values - Improved readability of queue allocation notification messages. Capacities are now displayed in KiB, e.g., `20:59:25 Quill INFO: Allocated a new SPSC queue with a capacity of 1024 KB (previously 512 KB) from thread 31158`. **New Features:** - Introduced support for custom buffer sizes in file streams for `FileSink` and `RotatingFileSink`. Buffer size is now configurable via `FileSinkConfig::set_write_buffer_size(size_value)` with a default of 64 KB. - Added an optional `fsync` interval to control the minimum time between consecutive `fsync` calls, reducing disk wear from frequent fsync operations. This option is only applicable when `fsync` is enabled. ([#557](https://github.com/odygrd/quill/issues/557)) - Implemented support for appending a custom timestamp format to log filenames via `StartCustomTimestampFormat`. Example usage: ```cpp auto file_sink = quill::Frontend::create_or_get_sink("logfile.log", []() { quill::FileSinkConfig cfg; cfg.set_filename_append_option(quill::FilenameAppendOption::StartCustomTimestampFormat, "%m%d"); return cfg; }()); ``` This will create a log file named `logfile0919.log`, where `0919` represents the month and day. - When using `%(named_args)` in the pattern formatter or logging in JSON format, extra arguments without key names are now included in JSON output with keys corresponding to their positional indexes. This allows additional details to be included in the JSON while keeping the log message clean. For example ([#563](https://github.com/odygrd/quill/discussions/563)): ```cpp LOG_INFO(hybrid_logger, "Operation {name} completed with code {code}", "Update", 123, "Data synced successfully"); ``` This will output: ``` Operation Update completed with code 123 ``` And the corresponding JSON will be: ``` {"timestamp":"1726582319816776867","file_name":"json_file_logging.cpp","line":"71","thread_id":"25462","logger":"hybrid_logger","log_level":"INFO","message":"Operation {name} completed with code {code}","name":"Update","code":"123","_2":"Data synced successfully"} ``` ## v7.1.0 - Fixed crash when using `QueueType::BoundedDropping` or `QueueType::UnboundedDropping` after a message drops. ([#553](https://github.com/odygrd/quill/issues/553)) - Improved performance of `ForwardList` decoding. - Corrected reported dropped message count; previously, log flush attempts were incorrectly included. - Removed leftover files after running some unit tests. - Stabilized regression tests. - Suppressed false-positive `-Wstringop-overflow` warnings (e.g., with GCC 13). - Fixed MinGW build and added MinGW builds to GitHub Actions. ## v7.0.0 - Simplified the log tags API. The `Tags` class has been removed. You now pass a `char const*` directly to the macros. Additionally, macros previously named `WITH_TAGS` have been renamed to `_TAGS`. For example, `LOG_INFO_WITH_TAGS` is now `LOG_INFO_TAGS`. - Renamed `backend_cpu_affinity` to `cpu_affinity` in `BackendOptions` to improve consistency. - Simplified project structure by removing the extra quill directory and made minor CMake improvements; `include/quill` is now directly in the root. - Added support for `std::string` with custom allocator. ([#524](https://github.com/odygrd/quill/issues/524)) - Added a new log level `NOTICE`, for capturing significant events that aren't errors or warnings. It fits between `INFO` and `WARNING` for logging important runtime events that require attention. ([#526](https://github.com/odygrd/quill/pull/526)) - Enhanced static assert error message for unsupported codecs, providing clearer guidance for STL and user-defined types. - Improved frontend performance by caching the `ThreadContext` pointer in `Logger` class to avoid repeated function calls. On Linux, this is now further optimised with `__thread` for thread-local storage, while other platforms still use `thread_local`. - Minor performance enhancement in the frontend by replacing `std::vector` with an `InlinedVector` for caching sizes (e.g. string arguments). - Fixed order of evaluation for `Codec::pair::compute_encoded_size()` to prevent side effects observed on MSVC - Introduced the `add_metadata_to_multi_line_logs` option in `PatternFormatter`. This option, now enabled by default, appends metadata such as timestamps and log levels to every line of multiline log entries, ensuring consistent log output. To restore the previous behavior, set this option to false when creating a `Logger` using `Frontend::create_or_get_logger(...)`. Note that this option is ignored when logging JSON using named arguments in the format message. ([#534](https://github.com/odygrd/quill/pull/534)) - `JSON` sinks now automatically remove any `\n` characters from format messages, ensuring the emission of valid `JSON` messages even when `\n` is present in the format. - Replaced `static` variables with `static constexpr` in the `ConsoleColours` class. - Fixed compiler errors in a few rarely used macros. Added a comprehensive test for all macros to prevent similar issues in the future. - Expanded terminal list for color detection in console applications on Linux - Fixed an issue where `char*` and `char[]` types could be incorrectly selected by the Codec template in `Array.h` - The library no longer defines `__STDC_WANT_LIB_EXT1__`, as the bounds-checking functions from the extensions are no longer needed. - `StringFromTime` constructor no longer relies on the system's current time, improving performance in simulations where timestamps differ from system time. ([#541](https://github.com/odygrd/quill/issues/541)) - The `Frontend::create_or_get_logger(...)` function now accepts a `PatternFormatterOptions` parameter, simplifying the API. This is a breaking change. To migrate quickly, wrap the existing formatting parameters in a `PatternFormatterOptions` object. **Before:** ```c++ quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(file_sink), "%(time) [%(thread_id)] %(short_source_location:<28) " "LOG_%(log_level:<9) %(logger:<12) %(message)", "%H:%M:%S.%Qns", quill::Timezone::GmtTime); ``` **After:** ```c++ quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(file_sink), quill::PatternFormatterOptions { "%(time) [%(thread_id)] %(short_source_location:<28) " "LOG_%(log_level:<9) %(logger:<12) %(message)", "%H:%M:%S.%Qns", quill::Timezone::GmtTime}); ``` ## v6.1.2 - Fix pkg-config file on windows ## v6.1.1 - Fix pkg-config file ## v6.1.0 - Fix various compiler warnings - Minor serialisation improvements in `Array.h` and `Chrono.h` - Introduced `Backend::acquire_manual_backend_worker()` as an advanced feature, enabling users to manage the backend worker on a custom thread. This feature is intended for advanced use cases where greater control over threading is required. ([#519](https://github.com/odygrd/quill/issues/519)) - Add new `CsvWriter` utility class for asynchronous CSV file writing. For example: ```c++ #include "quill/Backend.h" #include "quill/core/FrontendOptions.h" #include "quill/CsvWriter.h" struct OrderCsvSchema { static constexpr char const* header = "order_id,symbol,quantity,price,side"; static constexpr char const* format = "{},{},{},{:.2f},{}"; }; int main() { quill::BackendOptions backend_options; quill::Backend::start(backend_options); quill::CsvWriter csv_writer {"orders.csv"}; csv_writer.append_row(13212123, "AAPL", 100, 210.32321, "BUY"); csv_writer.append_row(132121123, "META", 300, 478.32321, "SELL"); csv_writer.append_row(13212123, "AAPL", 120, 210.42321, "BUY"); } ``` ## v6.0.0 - Added a [Cheat Sheet](https://quillcpp.readthedocs.io/en/latest/cheat_sheet.html) to help users get the most out of the logging library - Removed `ArgSizeCalculator<>`, `Encoder<>`, and `Decoder<>` classes. These have been consolidated into a single `Codec` class. Users who wish to pass user-defined objects should now specialize this single `Codec` class instead of managing three separate classes. For guidance, please refer to the updated advanced example - Added `TriviallyCopyableCodec.h` to facilitate serialization for trivially copyable user-defined types. For example ```c++ struct TCStruct { int a; double b; char c[12]; friend std::ostream& operator<<(std::ostream& os, TCStruct const& arg) { os << "a: " << arg.a << ", b: " << arg.b << ", c: " << arg.c; return os; } }; template <> struct fmtquill::formatter : fmtquill::ostream_formatter { }; template <> struct quill::Codec : quill::TriviallyCopyableTypeCodec { }; int main() { // init code ... TCStruct tc; tc.a = 123; tc.b = 321; tc.c[0] = '\0'; LOG_INFO(logger, "{}", tc); } ``` - Added support for passing arithmetic or enum c style arrays when `std/Array.h` is included. For example ```c++ #include "quill/std/Array.h" int a[6] = {123, 456}; LOG_INFO(logger, "a {}", a); ``` - Added support for `void const*` formatting. For example ```c++ int a = 123; int* b = &a; LOG_INFO(logger, "{}", fmt::ptr(b)); ``` - Added support for formatting `std::chrono::time_point` and `std::chrono::duration` with the inclusion of `quill/std/Chrono.h` ```c++ #include "quill/std/Chrono.h" std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); LOG_INFO(logger, "time is {}", now); ``` - Removed unused method from `ConsoleSink` ## v5.1.0 - Fix unit tests on FreeBSD ([#496](https://github.com/odygrd/quill/issues/496)) - Resolved unused variable warning on MSVC. - Updated CMake to avoid adding `-fno-exceptions` to the entire target when `QUILL_NO_EXCEPTIONS=ON` ([#499](https://github.com/odygrd/quill/issues/499)) - Fix an issue where timestamps were incorrectly calculated when using `quill::Timezone::LocalTime`. This bug affected timezones that did not have an exact hour difference from UTC, leading to incorrect timestamp calculations. ([#498](https://github.com/odygrd/quill/issues/498)) - The newline character `\n` is now considered printable by default and will no longer be sanitized. Users can now include new lines in their logs directly. In versions `4.4.1` and earlier, `\n` was not sanitized, and this behavior is restored in this update, eliminating the need for a custom `check_printable_char` function in `BackendOptions`. - On Windows, when colors are enabled in `ConsoleSink`, `GetConsoleScreenBufferInfo` may fail in the debug console. Previously, this would result in an error being displayed but no logs being written. This issue is now resolved: the error is reported once, and logs will be written to the console without colors. - Improved performance of `StringFromTime` and `TimestampFormatter` used by the backend worker thread. - Replaced `std::mutex` with a spinlock, resulting in minor performance improvement for backend worker. This change also avoids including `` in the frontend, particularly when following the [recommended_usage](https://github.com/odygrd/quill/blob/master/examples/recommended_usage/recommended_usage.cpp) example - Update bundled `libfmt` to `11.0.2` ## v5.0.0 - Fix build failure on Windows Arm64 ([#485](https://github.com/odygrd/quill/issues/485)) - Previously, wide string support was included in `Codec.h`. Wide string functionality has now been moved to a separate header file, `WideStrings.h`. On Windows, logging wide strings now requires the inclusion of `quill/std/WideStrings.h`. - Added `QUILL_IMMEDIATE_FLUSH` preprocessor variable. This variable can be defined before including `LogMacros.h` or passed as a compiler flag. When `QUILL_IMMEDIATE_FLUSH` is defined, the library will flush the log on each log statement. This causes the caller thread to wait for the log to be processed and written to the log file by the backend thread before continuing, significantly impacting performance. This feature is useful for debugging the application when synchronized logs are required. ([#488](https://github.com/odygrd/quill/issues/488)) - Introduced `log_level_descriptions` and `log_level_short_codes` in `BackendOptions` to allow customization of `LogLevel` descriptions and short codes, replacing previously hardcoded values. This enhancement enables users to define their own descriptions and short codes for each log level. For instance, instead of displaying `LOG_WARNING`, it can now be configured to show `LOG_WARN`. ([#489](https://github.com/odygrd/quill/issues/489)) ```c++ quill::BackendOptions backend_options; backend_options.log_level_descriptions[static_cast(quill::LogLevel::Warning)] = "WARN"; quill::Backend::start(backend_options); ``` - Introduced `LOGV_LEVEL`, `LOGV_LEVEL_LIMIT`, and `LOGV_LEVEL_WITH_TAGS` macros. These new macros simplify logging by automatically printing variable names and values without explicitly specifying each variable name or using `{}` placeholders in the format string. Each macro can handle up to 26 arguments. The format string is concatenated at compile time, there is no runtime overhead for using these macros. For example: ```c++ int a = 123; double b = 3.17; LOGV_INFO(logger, "A message with two variables", a, b) ``` outputs `A message with two variables [a: 123, b: 3.17]` - Introduced `LOGJ_LEVEL`, `LOGJ_LEVEL_LIMIT`, and `LOGJ_LEVEL_WITH_TAGS` macros. These new macros simplify JSON logging by automatically embedding the name of each passed variable as a named argument in the format string. Each macro can handle up to 26 arguments. The format string is concatenated at compile time, there is no runtime overhead for using these macros. For example: ```c++ int var_a = 123; std::string var_b = "test"; LOGJ_INFO(logger, "A json message", var_a, var_b); ``` outputs `{"log_level":"INFO","message":"A json message {var_a}, {var_b}","var_a":"123","var_b":"test"}` - Enhanced the `filter` function to also receive the formatted `log_message` alongside the log_statement, enabling the comparison and filtering of `log_message` while disregarding elements like timestamps from the full `log_statement`. ([#493](https://github.com/odygrd/quill/issues/493)) - Renamed `log_message` to `log_statement` and `should_log_message` to `should_log_statement` in `Logger` - Replaced `%(log_level_id)` with `%(log_level_short_code)` in the `PatternFormatter`. - Fix a `CMakeLists` error for old `CMake` versions prior to `3.19`. ([#491](https://github.com/odygrd/quill/issues/491)) ## v4.5.0 - The backend now automatically sanitizes non-printable characters in log messages by converting them to their hexadecimal representation. This feature ensures logs contain only safe, readable characters. You can customize or disable this feature through the backend options by modifying the `check_printable_char` callback in `BackendOptions`. ```c++ std::function check_printable_char = [](char c) { return c >= ' ' && c <= '~'; }; ``` - Added `StringRef`, a utility for passing string arguments by reference without copying. Suitable for string literals or immutable strings with a guaranteed persistent lifetime. For example ```c++ #include "quill/StringRef.h" static constexpr std::string_view sv {"string_view"}; LOG_INFO(logger, "{} {}", quill::utility::StringRef{sv}, quill::utility::StringRef{"string_literal"}); ``` - Renamed `write_log_message` to `write_log` in `Sink`. The formatted `log_message` and `process_id` are now also provided. This enhancement supports use cases where the formatted `log_statement` passed to the `Sink` can be ignored and overwritten with a custom format, allowing a single `Logger` to output different formats to various Sinks. ([#476](https://github.com/odygrd/quill/issues/476)) - Fixed a bug in JSON logging where previously cached named arguments could erroneously append to subsequent log statements. ([#482](https://github.com/odygrd/quill/issues/482)) ## v4.4.1 - Fixed multiple definitions of `quill::detail::get_error_message` ([#469](https://github.com/odygrd/quill/issues/469)) - Fixed an issue causing a `SIGABRT` when creating directories with a symlink folder path using GCC versions 8 or 9 ([#468](https://github.com/odygrd/quill/issues/468)) - Added an assertion to prevent the use of custom `FrontendOptions` together with default `FrontendOptions` ([#453](https://github.com/odygrd/quill/issues/453)) ## v4.4.0 - Introduced `log_timestamp_ordering_grace_period parameter`, replacing `enable_strict_log_timestamp_order` in `BackendOptions`. Enables strict timestamp ordering with configurable grace period. - Fixed an issue where symbols were not properly exported with hidden visibility when compiling as a shared library. ([#463](https://github.com/odygrd/quill/issues/463)) - Move version info into quill namespace ([#465](https://github.com/odygrd/quill/issues/465)) - Upstreamed `Meson` build integration. See details [here](https://github.com/odygrd/quill?tab=readme-ov-file#meson) - Upstreamed `Bazel` build integration. See details [here](https://github.com/odygrd/quill?tab=readme-ov-file#bazel) ## v4.3.0 - Refactored `BacktraceStorage` to simplify the code. - Fixed multiple definitions of `on_alarm` in `SignalHandler.h` - Fixed a bug in the backend thread where `flush()` and `run_periodic_tasks()` were skipped for certain sinks. All sinks are now correctly processed. ## v4.2.1 - Added `-Wno-gnu-zero-variadic-macro-arguments` as an interface compiler flag in CMake ## v4.2.0 - Fixed the compile-time exclusion of log levels. Renamed the `QUILL_COMPILE_OUT_LOG_LEVEL` preprocessor flag to `QUILL_COMPILE_ACTIVE_LOG_LEVEL`. - Fixed build error when `UnboundedDropping` queue is used. - Fixed a bug introduced in `v4.1.0`, which resulted in messages being logged out of order when the `transit_events_soft_limit` was reached. Additionally, this issue affected the behavior of `flush_log()`, prematurely unblocking the thread before all messages were flushed. - Fixed `-Wno-unused-parameter` and `-Wdocumentation` warnings. - Improved backend worker `_exit()` functionality and reduced code duplication in other areas of the backend worker code. - Added `signal_handler_timeout_seconds` parameter, which controls the timeout duration for the signal handler. Only available on Linux platforms. - Added `sleep_duration_ns` parameter to the `flush_log(...)` function. This parameter specifies the duration in nanoseconds to sleep between retries between checks for the flush completion and when a blocking queue is used, and it is full. The default sleep duration is 100 nanoseconds, but users can now customize this duration according to their needs. If a zero sleep duration is passed, the thread might yield instead. - Removed uses of `std::this_thread::sleep_for(...)`, `std::string`, `std::vector` in the signal handler when waiting for the log to be flushed. ## v4.1.0 - Following the transition from a compiled to a header-only library, the `target_compile_options` previously applied to the compiled library were mistakenly propagated to all programs linking against the header-only library. This issue is now fixed by removing those flags and explicitly adding them to tests and examples. As a result, executable targets no longer inherit flags from the library. - Removed unnecessary template specializations and merged their logic into the primary template for `ArgSizeCalculator`, `Encoder`, and `Decoder` using if constexpr. - Eliminated `` header dependency in the frontend - Replaced `%(structured_keys)` with `%(named_args)` in the `PatternFormatter`. This change now appends the entire key-value pair of named args to the message, not just the names. - Relocated certain classes to the `detail` namespace - Replaced `sprintf` with `snprintf` to fix macOS warning. - Reviewed and removed gcc cold attribute from a few functions. - Minor backend thread optimisations when logging c style strings or char arrays - Improved backend thread variable and function names and fixed a bug for an edge case when the transit event hard limit is reached ## v4.0.0 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 - This version significantly improves compile times. Taking a look at some compiler profiling for a `Release` build with clang 15, we can see the difference. Below are the two compiler flamegraphs for building the `recommended_usage` example from the new version and the `wrapper_lib` example from the previous version. 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](https://github.com/odygrd/quill/blob/master/docs/quill_v4_compiler_profile.speedscope.png) | | v3.8.0 | ![quill_v3_compiler_profile.speedscope.png](https://github.com/odygrd/quill/blob/master/docs/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](https://github.com/odygrd/quill/blob/master/benchmarks/compile_time/compile_time_bench.cpp). 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](https://github.com/odygrd/quill/blob/master/docs/quill_v4_compiler_bench.speedscope.png) | | v3.8.0 | ![quill_v3_compiler_bench.speedscope.png](https://github.com/odygrd/quill/blob/master/docs/quill_v4_compiler_profile.speedscope.png) | - Minor increase in backend thread throughput compared to the previous version. | 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 | - Significant boost in hot path latency when logging complex types such as `std::vector`. The performance remains consistent when logging only primitive types or strings in both versions. Refer [here](https://github.com/odygrd/quill?tab=readme-ov-file#performance) for updated and detailed benchmarks. #### Changes - **Improved compile times** 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. - **Backend formatting for user-defined and standard library types** 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: - Error-Prone Asynchronous Logging: Copying and formatting user-defined types on the backend thread in an asynchronous logging setup could lead to errors. Previous versions attempted to address this issue with type trait checks, which incurred additional template instantiations and compile times. - Uncertainty in Type Verification: It is challenging to confidently verify types, as some trivially copiable types, such as `struct A { int* m; }`, could still lead to issues due to potential modifications by the user before formatting. - Hidden Performance Penalties: Logging non-trivially copiable types could introduce hidden cache coherence performance penalties due to memory allocations and deallocations across threads. For instance, consider `std::vector` passed as a log argument. The vector is emplaced into the SPSC queue by the frontend, invoking the copy constructor dynamically allocating memory as the only members copied to SPSC queue are `size`, `capacity`, and `data*`. The backend thread reads the object, formats it, and then invokes the destructor, which in turn synchronizes the freed memory back to the frontend. 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](https://github.com/odygrd/quill/blob/master/examples/user_defined_types_logging.cpp). 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](https://github.com/odygrd/quill/blob/master/examples/advanced/advanced.cpp). - **Header-Only library** The library is now header-only. This change simplifies exporting the library as a C++ module in the future. See [here](https://github.com/odygrd/quill/blob/master/examples/recommended_usage/recommended_usage.cpp) on how to build a wrapper static library which includes the backend and will minimise the compile times. - **Preprocessor flags moved to template parameters** 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. - **Renamed Handlers to Sinks** To enhance clarity, handlers have been renamed to sinks. - **PatternFormatter moved to Logger** 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. - **Split Configuration** The configuration settings have been divided into `FrontendOptions` and `BackendOptions`. - **Refactoring of backend classes** `MacroMetadata` and many backend classes have undergone refactoring, resulting in reduced memory requirements. - **Improved wide strings handling on Windows** 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 - **Default logger removal** 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. - **Global logger removal** 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](https://github.com/odygrd/quill/blob/master/examples/recommended_usage/recommended_usage.cpp) - **Removal of printf style formatting support** 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. - **Removal of external libfmt usage** 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 - Revise include files to accommodate the removal of `Quill.h` - Update the code that starts the backend thread and the logger/sink creation. You can refer to any of the updated examples, such as [this one](https://github.com/odygrd/quill/blob/master/examples/file_logging.cpp) - When logging statements involving user-defined types, make sure these types are formatted into strings using your preferred method. Refer to [this link](https://github.com/odygrd/quill/blob/master/examples/user_defined_types_logging.cpp) for guidance. Alternatively, if you prefer delaying the conversion to strings until the backend thread and only passing a binary copy of the user-defined type on the hot path, you can provide the necessary class template specializations for each user-defined type. See an example [here](https://github.com/odygrd/quill/blob/master/examples/advanced/user_quill_codec.h) ## v3.9.0 - Fix bug in `ConsoleHandler` when dynamic log level is used ([#421](https://github.com/odygrd/quill/pull/421)) - Fix bug in `TransitEvent` when dynamic log level is used ([#427](https://github.com/odygrd/quill/pull/427)) - Fix build error for Intel compiler classic ([#414](https://github.com/odygrd/quill/pull/414)) - Added `JsonConsoleHandler` ([#413](https://github.com/odygrd/quill/issues/413)) - Fix fold expression argument evaluation. This bug could occur when logging c style strings ## v3.8.0 - Refactored `MacroMetadata` class to reduce its size. - Renamed some attributes in the `PatternFormatter` class for clarity. If you are using a custom format pattern, update the attribute names in your code to match the new names. - Improved accuracy of log statement timestamps. Previously, the timestamp was taken after checking if the queue had enough space to push the message, which could make it less accurate. Additionally, in the case of a blocking queue, the timestamp could be later in time. Now, the timestamp is taken and stored right after the log statement is issued, before checking for the queue size. - Reduced template instantiations during logging operations on the hot path. Fold expressions are now used for encoding/decoding arguments, minimizing template recursion overhead. - Removed compile-time format checks due to their significant impact on template instantiations, especially considering that only a few cases are invalid. For instance, while `fmt::format("{}", 1, 2)` is considered valid, `fmt::format("{} {}", 1)` is deemed invalid. In cases where an invalid format string is detected, the backend worker thread catches the generated exception and logs an error. - The throughput of the backend worker thread has been improved by approximately 5%. This enhancement is reflected in the new throughput value of 4.20 million msgs/sec, compared to the previous throughput of 3.98 million msgs/sec. - Detect `tmux` as colour terminal. ([#410](https://github.com/odygrd/quill/issues/410)) ## v3.7.0 - Fixed crash triggered by insufficient space in the queue upon invocation of ``flush()``. ([#398](https://github.com/odygrd/quill/pull/398)) - Fixed windows clang-cl build error. ([#400](https://github.com/odygrd/quill/pull/400)) - Fixed compilation errors encountered on FreeBSD and extended ``get_thread_id()`` support to various other BSD operating systems. ([#401](https://github.com/odygrd/quill/pull/401)) - Fix open_file in the FileHandler to also create the parent path before opening the file. ([#395](https://github.com/odygrd/quill/issues/395)) - Enhance logic for backend thread's flush() invocation; it now triggers only if the handler has previously written data. ([#395](https://github.com/odygrd/quill/issues/395)) - Address an uncaught exception in the backend thread that could occur when a user manually removes the log file from the terminal while the logger is running. ([#395](https://github.com/odygrd/quill/issues/395)) - Ensure that after a logger is removed, there are no subsequent calls to the Handler's flush() or run_loop(), provided the Handler is not shared. ([#395](https://github.com/odygrd/quill/issues/395)) - Ignore the virtual destructor missing warning for the `CustomTags` class. ([#402](https://github.com/odygrd/quill/pull/402)) - Update bundled `libfmt` to `v10.2.1` ## v3.6.0 - Fixed `QUILL_LOGGER_CALL_NOFN_LIMIT` macros. ([#381](https://github.com/odygrd/quill/pull/381)) - Resolved a bug that caused reading destructed arguments when structured logging format was used. - Modified member access from `private` to `protected` in `ConsoleHandler` for potential inheritance purposes. - Eliminated redundant whitespaces within `JsonFileHandler`. - Fixed `JsonFileHandler` to notify the file event notifier before log message writes. - Implemented a new attribute called `%(structured_keys)` within the `PatternFormatter` to facilitate the inclusion of keys in messages when using structured log formatting. This addition is useful for instances where logging occurs in both JSON and regular log formats, enabling the display of keys within the regular log-formatted messages. See updated [example_json_structured_log.cpp](https://github.com/odygrd/quill/blob/master/examples/example_json_structured_log.cpp) ## v3.5.1 - Resolved issue with accessing the `name()` method within the `Logger` class. ([#378](https://github.com/odygrd/quill/pull/378)) - Fixed a compilation error in `SignalHandler` specific to Windows when `QUILL_DISABLE_NON_PREFIXED_MACROS` is defined. ([#380](https://github.com/odygrd/quill/pull/380)) ## v3.5.0 - Fixed `LOG_TRACE_CFORMAT` macros. - Added support for compile-time custom tags in `quill::MacroMetadata` to enhance message filtering and incorporate static information. New log macros suffixed with `_WITH_TAGS` introduced for this feature. Additionally, `%(custom_tags)` parameter added to `PatternFormatter`. ([#349](https://github.com/odygrd/quill/issues/349)) See [example_custom_tags.cpp](https://github.com/odygrd/quill/blob/master/examples/example_custom_tags.cpp) - Improvements to reduce compilation time ## v3.4.1 - Reduce backend worker unnecessary allocation. ([#368](https://github.com/odygrd/quill/issues/368)) - Adjusted handling for empty `std::string_view` instances, addressing an issue where logging empty strings triggered an unintended `memcpy` with zero size and a nullptr, leading to address sanitizer warnings. - Fix clang build error when using `-DQUILL_NO_EXCEPTIONS:BOOL=ON`. ([#357](https://github.com/odygrd/quill/issues/357)) ## v3.4.0 - Resolved `bad_variant_access` error occurring when using Quill as a pre-compiled library with a distinct queue type. ([#276](https://github.com/odygrd/quill/pull/276)) - Resolved a bug in `RotatingFileHandler` associated with logfiles located outside the working directory, specifically when used with open_mode `a`. ([#340](https://github.com/odygrd/quill/pull/340)) - Added a `name()` method to the Logger class which provides the logger name. ([#345](https://github.com/odygrd/quill/pull/345)) - Fixed library and include paths in the pkg-config configuration. ([#352](https://github.com/odygrd/quill/pull/352)) - Move `get_root_logger()` definition from cpp to the header file ([#348](https://github.com/odygrd/quill/issues/348)) - Introduced support for logging character arrays. You can now log character arrays, even when they don't contain a null-terminating character. Additionally, character arrays with null characters in the middle are supported, and the logger will capture the content until the null character is encountered. ([#353](https://github.com/odygrd/quill/pull/353)) For example ```c++ union { char no_0[2]; char mid_0[6]{'1', '2', '3', '4', '\0', 6}; } char_arrays; // only output "12" even if there's no '\0' at the end LOG_INFO(logger, R"(This is a log info example for char array without '\0': {})", char_arrays.no_0); // output "1234" until the '\0' LOG_INFO(logger, R"(This is a log info example for char array with '\0' in middle: {})", char_arrays.mid_0); ``` - Minor improvements in the bounded queue and throughput. ([#362](https://github.com/odygrd/quill/pull/362)) Previous: 2.21 million msgs/sec average, total time elapsed: 1809 ms for 4000000 log messages. New: 2.24 million msgs/sec average, total time elapsed: 1787 ms for 4000000 log messages. - Disable `fmt::join(data, "")` at compile time. ([#356](https://github.com/odygrd/quill/issues/356)) - Fix compile error in Apple Clang 12. ([#360](https://github.com/odygrd/quill/issues/360)) - Add guards for redefined preprocessor variables. - Fix `uint64_t` to `time_t` implicit conversion error in Clang 18. - Update bundled `libfmt` to `v10.1.1` ## v3.3.1 - Fixed `RotatingFileHandler` to prevent accidental removal of non-log files when using open mode `w` and `set_remove_old_files(true)` ## v3.3.0 - Added a `quill::get_handler(handler_name)` function that allows easy lookup of an existing `Handler` by name. This function proves helpful when you want to retrieve a handler and pass it to a new logger. - Fix build failure of Intel Compiler Classic. ([#332](https://github.com/odygrd/quill/pull/332)) - Introduced `QUILL_BLOCKING_QUEUE_RETRY_INTERVAL_NS` option for user-configurable retry interval in the blocking queue. Default value is 800 nanoseconds. ([#330](https://github.com/odygrd/quill/pull/330)) - Improved backend thread handling. Now verifies that all producer SPSC queues are empty before entering `sleep`. - Fixed a race condition and potential crash in `quill::remove_logger(Logger*)` when called without prior `quill::flush()`. - Added protection to prevent removal of the root logger with `quill::remove_logger(Logger*)`. - Improved exception handling on the backend thread when calling `fmt::format()`. While compile-time checks ensure that the format string and arguments match, runtime errors can still occur. Previously, such exceptions would affect and drop subsequent log records. Now, exceptions are caught and logged in the log file and reported via the backend thread notification handler (default is `cerr`). For example, if a dynamic precision is used (`LOG_INFO(logger, "Support for floats {:.{}f}", 1.23456, 3.321312)`), the log file will show the following error message: ``` LOG_INFO root [format: "Support for floats {:.{}f}", error: "precision is not integer"] ``` Additionally, an error message will be printed to `cerr` ``` Quill ERROR: [format: "Support for floats {:.{}f}", error: "precision is not integer"] ``` - Fixed a bug in timestamp formatting that occasionally displayed an hour component of 0 as 24. ([#329](https://github.com/odygrd/quill/pull/329)) - Added support for specifying a runtime log level, allowing dynamic log level configuration at runtime. The new runtime log level feature provides flexibility when needed, with a minor overhead cost. It is recommended to continue using the existing static log level macros for optimal performance. ([#321](https://github.com/odygrd/quill/pull/321)) For example ```c++ std::array const runtime_log_levels = {quill::LogLevel::Debug, quill::LogLevel::Info, quill::LogLevel::Warning, quill::LogLevel::Error}; for (auto const& log_level : runtime_log_levels) { LOG_DYNAMIC(logger, log_level, "Runtime {} {}", "log", "level"); } ``` - Added support for printf-style formatting with `_CFORMAT` macros. These macros use the `printf` format string syntax, simplifying the migration of legacy codebases using `printf` statements. For example ```c++ std::array arr = {1, 2, 3, 4}; LOG_INFO(logger, "This is a log info example using fmt format {}", arr); LOG_INFO_CFORMAT(logger, "printf style %s supported %d %f", "also", 5, 2.32); ``` - Added a `metadata()` member function to the `TransitEvent` class. It provides access to the `Metadata` object associated with the log record, simplifying syntax for retrieving log record metadata in custom Handlers. For example ```c++ void CustomHandler::write(fmt_buffer_t const& formatted_log_message, quill::TransitEvent const& log_event) { MacroMetadata const macro_metadata = log_event.metadata(); } ``` - Simplified file handler configuration. Now, instead of passing multiple arguments to the constructor, you only need to provide a single `FileHandlerConfig` object. This change makes creating file handlers objects much easier and more flexible. For example ```c++ quill::FileHandlerConfig file_handler_cfg; file_handler_cfg.set_open_mode('w'); file_handler_cfg.set_append_to_filename(quill::FilenameAppend::StartDateTime); std::shared_ptr file_handler = quill::file_handler("application.log", file_handler_cfg); quill::Logger* logger_foo = quill::create_logger("my_logger", std::move(file_handler)); LOG_INFO(my_logger, "Hello from {}", "application"); ``` - Combined the functionalities of `RotatingFileHandler` (rotating based on file size) and `TimeRotatingFileHandler` (rotating on a time interval) into a single, more versatile `RotatingFileHandler`. Users can now conveniently rotate logs based on both file size and time intervals simultaneously. The updated `RotatingFileHandler` offers a variety of customization options for improved flexibility. For more information on available configurations, refer to the `RotatingFileHandlerConfig` documentation. For example ```c++ // Create a rotating file handler which rotates daily at 18:30 or when the file size reaches 2GB std::shared_ptr file_handler = quill::rotating_file_handler(filename, []() { quill::RotatingFileHandlerConfig cfg; cfg.set_rotation_time_daily("18:30"); cfg.set_rotation_max_file_size(2'000'000'000); return cfg; }()); // Create a logger using this handler quill::Logger* logger_bar = quill::create_logger("daily_logger", std::move(file_handler)); ``` - Improved compatibility with older versions of external `libfmt`. Quill now compiles for all versions of `libfmt >= 8.0.0`. ## v3.2.0 - Addition of std::is_trivially_copyable to default copy loggable types. ([#318](https://github.com/odygrd/quill/pull/318)) - By default, the static library now builds with '-fPIC' to generate position-independent code. To disable this feature, you can use the CMake option 'QUILL_DISABLE_POSITION_INDEPENDENT_CODE'. - The `LOG__LIMIT` macros now support using `std::chrono` duration types for specifying the log interval. Instead of providing a raw number, you can use: ```c++ LOG_INFO_LIMIT(std::chrono::milliseconds {100} , quill::get_logger(), "log message"); ``` ## v3.1.0 - It is now possible to set a minimum logging interval for specific logs. For example: ```c++ for (uint64_t i = 0; i < 10; ++i) { LOG_INFO_LIMIT(2000, default_logger, "log in a loop with limit 1 message every 2000 micros for i {}", i); std::this_thread::sleep_for(std::chrono::microseconds{1000}); } ``` - `quill::utility::to_string()` now uses `fmt::to_string()` - Quill now utilizes a custom namespace (`fmtquill`) for the bundled fmt library. This enables smooth integration with your own external fmt library, even if it's a different version. ## v3.0.2 - Add missing header on clang when `QUILL_X86ARCH` is defined. ## v3.0.1 - Enhanced the reported message for reallocation of the unbounded queue to include the thread id. ## v3.0.0 - The previous unbounded queue constantly reallocated memory, risking system memory exhaustion, especially when handling intensive logging from multiple threads. Starting from `v3.0.0`, the default behavior has been improved to limit the queue capacity to 2 GB. When this limit is reached, the queue blocks the hot thread instead of further reallocation. To modify the default behavior, there is no need to recompile the `quill` library. Recompile your application with one of the following header-only flags. ```shell # Previous behavior in v2.*.*: Reallocates new queues indefinitely when max capacity is reached -DCMAKE_CXX_FLAGS:STRING="-DQUILL_USE_UNBOUNDED_NO_MAX_LIMIT_QUEUE" # Default behavior in v3.*.*: Starts small, reallocates up to 2GB, then hot thread blocks -DCMAKE_CXX_FLAGS:STRING="-DQUILL_USE_UNBOUNDED_BLOCKING_QUEUE" # Starts small, reallocates up to 2GB, then hot thread drops log messages -DCMAKE_CXX_FLAGS:STRING="-DQUILL_USE_UNBOUNDED_DROPPING_QUEUE" # Fixed queue size, no reallocations, hot thread drops log messages -DCMAKE_CXX_FLAGS:STRING="-DQUILL_USE_BOUNDED_QUEUE" # Fixed queue size, no reallocations, hot thread blocks -DCMAKE_CXX_FLAGS:STRING="-DQUILL_USE_BOUNDED_BLOCKING_QUEUE" ``` - Added support for huge pages on Linux. Enabling this feature allows bounded or unbounded queues to utilize huge pages, resulting in optimised memory allocation. ```c++ quill::Config cfg; cfg.enable_huge_pages_hot_path = true; quill::configure(cfg); quill::start(); ``` - Added support for logging `std::optional`, which is also now supported in `libfmt` `v10.0.0`. ```c++ LOG_INFO(default_logger, "some optionals [{}, {}]", std::optional{}, std::optional{"hello"}); ``` - Introduced a new function `run_loop` in the `Handler` base class, which allows users to override and execute periodic tasks. This enhancement provides users with the flexibility to perform various actions at regular intervals, such as batch committing data to a database. - In scenarios where a hot thread is blocked and unable to push messages to the queue in blocking mode, this situation will now be reported through the `backend_thread_notifications_handler` to the standard error stream `cerr`. ## v2.9.2 - Fix increased compile times due to `x86intrin` headers. ([#298](https://github.com/odygrd/quill/pull/298)) - Fix compile error when using `QUILL_X86ARCH` on windows. - Fix bugs when quill is build as a shared library on windows. ([#302](https://github.com/odygrd/quill/pull/302)) ## v2.9.1 - Removed `CMAKE_INSTALL_RPATH` from cmake. ([#284](https://github.com/odygrd/quill/pull/284)) - Fix compile warning on Apple M1. ([#291](https://github.com/odygrd/quill/pull/291)) - Update bundled `libfmt` to `v10.0.0` - Fix for `CMAKE_MODULE_PATH` ([#295](https://github.com/odygrd/quill/pull/295)) - Fixed a bug in `TimeRotatingFileHandler` when `quill::FilenameAppend::None` is used. ([#296](https://github.com/odygrd/quill/pull/296)) - Fixed `TimeRotatingFileHandler` and `RotatingFileHandler` to work when `/dev/null` is used as a filename ([#297](https://github.com/odygrd/quill/pull/297)) - Added `NullHandler` that can be used to discard the logs. For example: ```c++ int main() { quill::start(); std::shared_ptr file_handler = quill::null_handler(); quill::Logger* logger_bar = quill::create_logger("nullhandler", std::move(file_handler)); for (uint32_t i = 0; i < 150; ++i) { LOG_INFO(logger_bar, "Hello"); } ``` ## v2.9.0 **Fixes** - Fixed a bug in TimeRotatingFileHandler. ([#287](https://github.com/odygrd/quill/pull/287)) **Improvements** - Renamed `backend_thread_error_handler` to `backend_thread_notifications_handler` in `Config.h`. Previously this handler was used only to report errors from the backend worker thread to the user. This callback will also now report info messages to the user. - Report unbounded spsc queue reallocation via the `backend_thread_notifications_handler`. ([#286](https://github.com/odygrd/quill/pull/286)) - Report bounded spsc queue dropped messages via the `backend_thread_notifications_handler`. ## v2.8.0 **Breaking Changes** (see `improvements` section for more details) - If you were previously compiling with `-DQUILL_USE_BOUNDED_QUEUE` or `QUILL_X86ARCH` you should now pass the flag to you target as it is not propagated by CMake anymore. - There is a change in the API in `Quill.h` instead of `quill::Handler*` you should now use `std::shared_ptr< quill::Handler >` and also move it to the created logger. **Improvements** - Add `append_to_filename` parameter when creating `quill::time_rotating_file_handler` and `quill::rotating_file_handler` - Fix `Handlers` failing to find the file when the working directory of the application is changed in runtime. ([#247](https://github.com/odygrd/quill/pull/247)) - When the given output directory of a log file passed to a `Handler` does not exist, it will now get automatically created. - Support Windows 10 LTSB 2016, 1607 and Server 2016. ([#251](https://github.com/odygrd/quill/pull/251)) - Add back `backend_thread_sleep_duration` in `Config.h` ([#256](https://github.com/odygrd/quill/pull/256)) - For `quill::rotating_file_handler(...)` and `quill::time_rotating_file_handler(...)` the `backup_count` argument is now default to `std::numeric_limits::max()` - When the logging file is deleted from the command line while the logger is still using it, then a new file will be reopened for writing. - Added `quill::Clock` which enables taking and converting TSC timestamps to system clock timestamps. When `TimestampClockType::Tsc` is used as the default clock type in `Config.h` this class can also be used to generate timestamps that are in sync with the timestamps in the log file. ([#264](https://github.com/odygrd/quill/pull/264)) - Both `Unbounded` and `Bounded` queue modes can now be used without having to recompile `quill` library. This is still not a runtime option, you still need to recompile your target and pass `QUILL_USE_BOUNDED_QUEUE` as a flag. See [example_bounded_queue_message_dropping.cpp](https://github.com/odygrd/quill/blob/master/examples/example_bounded_queue_message_dropping.cpp) - Added `QUILL_USE_BOUNDED_BLOCKING_QUEUE` option that makes possible to use a bounded queue which blocks the hot thread rather than dropping messages ([#270](https://github.com/odygrd/quill/pull/270)) See [example_bounded_queue_blocking.cpp](https://github.com/odygrd/quill/blob/master/examples/example_bounded_queue_blocking.cpp) - Renamed `backend_thread_max_transit_events` to `backend_thread_transit_events_soft_limit` in Config.h ([#270](https://github.com/odygrd/quill/pull/270)) - Added `backend_thread_transit_events_hard_limit` in Config.h ([#270](https://github.com/odygrd/quill/pull/270)) - Added `backend_thread_use_transit_buffer` in Config.h ([#270](https://github.com/odygrd/quill/pull/270)) - CMake: `QUILL_X86ARCH` and `QUILL_USE_BOUNDED_QUEUE` options have been removed. The users can decide on enabling these options on their side and quill doesn't need to be recompiled as a library. For example : ```cmake target_compile_definitions( PUBLIC QUILL_X86ARCH QUILL_USE_BOUNDED_QUEUE) ``` - Added `quill::remove_logger(Logger* logger)` in `Quill.h`. This makes it possible to remove a logger in a thread safe way. When a logger is removed any associated `FileHandlers` with that logger will also be removed and the files will also be closed as long as they are not being used by another logger. The logger is asynchronously removed by the logging thread after all the messages are written. To achieve this the API had to change to return a `std::shared_ptr< quill::Handler >` instead of `quill::Handler*`. See [example_file_callbacks.cpp](https://github.com/odygrd/quill/blob/master/examples/example_file_callbacks.cpp) - Added `quill::wake_up_logging_thread()` in `Quill.h`. This thread safe function can be used to wake up the backend logging thread on demand. ([#280](https://github.com/odygrd/quill/pull/280)) - Round up queue capacity to the nearest power of 2. ([#282](https://github.com/odygrd/quill/pull/282)) ## v2.7.0 **Fixes** - Remove references to build directory path from the compiled library's symbols. ([#221](https://github.com/odygrd/quill/pull/221)) - Fix when compiled as shared library with hidden visibility. ([#222](https://github.com/odygrd/quill/pull/222)) - Fix equal timestamp log messages appearing out of order. ([#223](https://github.com/odygrd/quill/pull/223)) - Reduce padding in some structs. - Fix 'rename_file' throwing an exception while being marked as `noexcept`. ([#230](https://github.com/odygrd/quill/pull/230)) - Fix crash with `std::bad_alloc` and compiler warnings in gcc `7.3.1`. ([#235](https://github.com/odygrd/quill/pull/235)) - The additional compiler definitions will now be propagated to the parent targets when enabling options in CMake. ([#235](https://github.com/odygrd/quill/pull/235)) **Improvements** - Improved performance and throughput of the backend logging thread by approximately ~25% - Add missing `quill::json_file_handler(...)` that creates a `JsonFileHandler` in `Quill.h`. - Simplified and refactored the logic in `BoundedQueue`. - Added the option `do_fsync` which also calls `fsync()` during the handler flush to all file handlers. - Replace `backend_thread_sleep_duration` with `backend_thread_yield` in `Config.h` - Remove trailing spaces in log levels strings. ([#237](https://github.com/odygrd/quill/pull/237)) - The default log pattern has changed to `"%(ascii_time) [%(thread)] %(fileline:<28) LOG_%(level_name:<9) %(logger_name:<12) %(message)")` - Added file event notifiers, to get callbacks from quill before/after log file has been opened or closed. ([#193](https://github.com/odygrd/quill/pull/193)) This is useful for cleanup procedures or for adding something to the start/end of the log files. for example ```c++ int main() { quill::start(); quill::FileEventNotifier fen; fen.before_open = [](quill::fs::path const& filename) { std::cout << "before opening " << filename << std::endl; }; fen.after_open = [](quill::fs::path const& filename, FILE* f) { std::cout << "after opening " << filename << std::endl; }; fen.before_close = [](quill::fs::path const& filename, FILE* f) { std::cout << "before closing " << filename << std::endl; }; fen.after_close = [](quill::fs::path const& filename) { std::cout << "after closing " << filename << std::endl; }; quill::Handler* file_handler = quill::file_handler("myfile.log", "w", quill::FilenameAppend::None, std::move(fen)); quill::Logger* mylogger = quill::create_logger("mylogger", file_handler); LOG_INFO(mylogger, "Hello world"); } ``` - Added `QUILL_X86ARCH` in `Tweakme.h`. When enabled it will attempt to minimize the cache pollution on x86 cpus that support the instructions `_mm_prefetch `, `_mm_clflush` and `_mm_clflushopt`. To compile when this flag is enabled you should also pass `-march` to the compiler which is required, you can set this to your oldest cpu architecture among your systems. To enable this option, `DQUILL_X86ARCH` must always be defined in quill library and also in your executable, for example ```shell cmake -DCMAKE_CXX_FLAGS:STRING="-DQUILL_X86ARCH -march=native" ``` - Added `quill:get_root_logger()` which gives quick access to the root logger object and can be used directly in the hot path. This gives applications that only wish to use the root logger the convenience of not having to store and pass `Logger*` objects anymore. for example quill existing log macros can be overwritten to not require a `Logger*` anymore ```c++ #define MY_LOG_INFO(fmt, ...) QUILL_LOG_INFO(quill::get_root_logger(), fmt, ##__VA_ARGS__) `````` - Added `QUILL_ROOT_LOGGER_ONLY` in `Tweakme.h`. Define ths if you only plan to use the single `root` logger object, When this is defined it will replace the LOG_ macros with the equivalent LOG_ macros but without the need of passing `Logger*` objects anymore. for example ```c++ #define QUILL_ROOT_LOGGER_ONLY #include "quill/Quill.h" int main() { quill::start(); // because we defined QUILL_ROOT_LOGGER_ONLY we do not have to pass a logger* anymore, the root logger is always used LOG_INFO("Hello {}", "world"); LOG_ERROR("This is a log error example {}", 7); } ``` ## v2.6.0 **Fixes** - Fix filepath on Windows when MinGW is used. ([#212](https://github.com/odygrd/quill/pull/212)) **Improvements** - Removed the creation of `static Metadata` objects during initialisation time. - `#define QUILL_QUEUE_CAPACITY` has been removed. - Added Config option `default_queue_capacity` that can be used to specify the initial capacity of the queue. - When Unbounded queue is used the newly allocated queue will now have enough space to fit any object. ([#215](https://github.com/odygrd/quill/pull/215)) ## v2.5.1 **Improvements** - Reduced the allocations performed by the backend worker thread as the same objects are now being reused rather than destroyed. **Summary of changes since v2.3.2** In version `2.3.2` when multiple threads performed heavy logging, the backend logging thread incorrectly gave priority to the logs of the same threads. That made logs from the remaining threads to appear much later or sometimes never in the log files. There was a series of fixes and releases to address this. Below is the summary of the changes from `v2.3.2` - Previously when multiple threads were logging, the backend logging thread would first try to read the log messages of the same thread until its queue was completely empty before reading the log messages of the next thread. When one of the threads was logging a lot, it could result in only displaying the log of that thread, hiding the logs of the other threads. This has now been fixed and all log messages from all threads are read fairly. - Optimise the backend logging thread to read all log messages from each queue. Ensure all queues from all active threads are fairly read. - `fmt::basic_memory_buffer` buffer stack size has been reduced. The backend thread shows better performance with a reduced stack size. This also reduces the risk of a stack overflow when too many log messages are cached.lllllllllll - Reduced the allocations performed by the backend worker thread as the same objects are now being reused rather than destroyed. - Added a config option `backend_thread_strict_log_timestamp_order`. This option enables an extra timestamp check on the backend logging thread when each message is popped from the queues. It prevents a rare situation where log messages from different threads could appear in the log file in the wrong order. This flag is now enabled by default. - Added a config option `backend_thread_empty_all_queues_before_exit`. This option makes the backend logging thread to wait until all the queues are empty before exiting. This ensures no log messages are lost when the application exists. This flag is now enabled by default. ## v2.5.0 **Improvements** - Performance improvements for the backend logging thread ## v2.4.2 **Fixes** - Fixes an assertion that was triggered in debug mode due to changes in v2.4.1 ## v2.4.1 **Improvements** - Previously the backend worker thread would read all the log messages from the queue but not read the log messages when the buffer had wrapped around. It will now read all the messages. - Removed the `min_available_bytes` cache from the SPSC queue as an optimisation. It is not needed anymore as we now read all messages at once instead of reading message by message. ## v2.4.0 **Improvements** - Added a config option `backend_thread_strict_log_timestamp_order`. This option enables an extra timestamp check on the backend logging thread when each message is popped from the queues. It prevents a rare situation where log messages from different threads could appear in the log file in the wrong order. This flag is now enabled by default. - Added a config option `backend_thread_empty_all_queues_before_exit`. This option makes the backend logging thread to wait until all the queues are empty before exiting. This ensures no log messages are lost when the application exists. This flag is now enabled by default. ## v2.3.4 **Improvements** - Optimise the backend logging thread to read multiple log messages from the same queue, but still fairly read each queue from all active threads. ## v2.3.3 **Fixes** - Previously when multiple threads were logging, Quill backend logging thread would first try reading the log messages of one thread until the queue was completely empty before reading the log messages of the next thread. When one of the threads was logging a lot, it could result in only displaying the log of that thread, hiding the logs of the other threads. This has now been fixed and all log messages from all threads are read fairly. ## v2.3.2 **Fixes** - Fix code not compiling with treat warnings as errors set on Windows. ([#198](https://github.com/odygrd/quill/pull/198)) ## v2.3.1 **Fixes** - Optimise logging queue cache alignment of variables. It seems that v2.3.0 made the hot path slower by ~5 ns per message. This has been fixed in this version and the performance is now the same as in the previous versions. ## v2.3.0 **Improvements** - Cache the available bytes for reading in the logging queue. This is meant to offer some minor performance improvement to the backend logging thread. [#185](https://github.com/odygrd/quill/issues/185) - Fixed static code analysis and clang '-Wdocumentation' warnings. - The `Handler.h` API has changed in this version to support structured logs. If you have implemented your own custom `Handler` you will have to change it to follow the new API. - This version adds support for writing structured logs. Structured logs provide easier search through events. Structured logging is automatically enabled when named arguments are provided to the format string. Structured logs are only supported by the new `quill::JsonFileHandler` handler. The already existing `FileHandler` and `ConsoleHandler` are compatible with named arguments, but they will ignore them and output the log in its original format, as defined by the pattern formatter. Structured logs are not supported for wide characters at the moment. See [example_json_structured_log.cpp](https://github.com/odygrd/quill/blob/master/examples/example_json_structured_log.cpp) For example : ```c++ quill::start(); quill::Handler* json_handler = quill::create_handler("json_output.log", "w"); // create another logger tha logs e.g. to stdout and to the json file at the same time quill::Logger* logger = quill::create_logger("dual_logger", {quill::stdout_handler(), json_handler}); for (int i = 2; i < 4; ++i) { LOG_INFO(logger, "{method} to {endpoint} took {elapsed} ms", "POST", "http://", 10 * i); } ``` 1) Will write to stdout (stdout_handler) : ```` 23:37:19.850432433 [11811] example_json_structured_log.cpp:39 LOG_INFO dual_logger - POST to http:// took 20 ms 23:37:19.850440154 [11811] example_json_structured_log.cpp:39 LOG_INFO dual_logger - POST to http:// took 30 ms ```` 2) Will produce a JSON file (json_handler) : ``` { "timestamp": "23:37:19.850432433", "file": "example_json_structured_log.cpp", "line": "39", "thread_id": "11811", "logger": "dual_logger", "level": "Info", "message": "{method} to {endpoint} took {elapsed} ms", "method": "POST", "endpoint": "http://", "elapsed": "20" } { "timestamp": "23:37:19.850440154", "file": "example_json_structured_log.cpp", "line": "39", "thread_id": "11811", "logger": "dual_logger", "level": "Info", "message": "{method} to {endpoint} took {elapsed} ms", "method": "POST", "endpoint": "http://", "elapsed": "30" } ``` ## v2.2.0 **Improvements** - Previously storing the default root logger by calling `quill::get_logger()` followed by `quill::configure(cfg)` would invalidate the pointer to the default root logger returned by the former function. This has now been fixed and the obtained `Logger*` pointer is still valid. - Disable `fmt::streamed()`. ([#189](https://github.com/odygrd/quill/issues/189)) - Update bundled fmt to 9.1.0 - `logger->should_log(level)` is removed. A compile time check was added to `logger->should_log()` . ([#187](https://github.com/odygrd/quill/issues/187)) ## v2.1.0 **Improvements** This version includes breaking changes to the API. Those changes are related to how quill is configured, before calling `quill::start()` to start the backend thread. Check the updated [examples](https://github.com/odygrd/quill/blob/master/examples). [Config.h](https://github.com/odygrd/quill/blob/master/quill/include/quill/Config.h) - contains runtime configuration options [TweakMe.h](https://github.com/odygrd/quill/blob/master/quill/include/quill/TweakMe.h) - contains compile time configuration For example `quill::set_default_logger_handler(...)` has been removed. To set a default filehandler : ```cpp // create a handler quill::Handler* file_handler = quill::file_handler("test.log", "w"); file_handler->set_pattern( "%(ascii_time) [%(thread)] %(fileline:<28) %(level_name) %(logger_name:<12) - %(message)", "%Y-%m-%d %H:%M:%S.%Qms", quill::Timezone::GmtTime); // set the handler as the default handler for any newly created logger in the config quill::Config cfg; cfg.default_handlers.emplace_back(file_handler); // configure must always be called prior to `start()` quill::configure(cfg); quill::start(); ``` - Removed some API functions from `Quill.h` that were previously used for configuration. Instead, `quill::Config` object has to be created. For example `quill::config::set_backend_thread_cpu_affinity(1);` has been removed and instead the following code is needed : ```cpp quill::Config cfg; cfg.backend_thread_cpu_affinity = 1; quill::configure(cfg); ``` - `QUILL_CHRONO_CLOCK` has been moved from `TweakMe.h` to `Config.h`. It is now possible to switch between `rdtsc` and `system` clocks without re-compiling. See [example_trivial_system_clock.cpp](https://github.com/odygrd/quill/blob/master/examples/example_trivial_system_clock.cpp) - `QUILL_RDTSC_RESYNC_INTERVAL` has been moved from `TweakMe.h` to `Config.h`. - It is now possible to log user timestamps rather than the system's. This feature is useful for time simulations. See [example_custom_clock.cpp](https://github.com/odygrd/quill/blob/master/examples/example_custom_clock.cpp) and [example_custom_clock_advanced.cpp](https://github.com/odygrd/quill/blob/master/examples/example_custom_clock_advanced.cpp) - Previously the logger names were limited to a maximum of 22 characters. This limitation has been removed. - Added support for gcc 7.5.0. ([#178](https://github.com/odygrd/quill/issues/178)) - Updated bundled fmt to 9.0.0 ## v2.0.2 **Fixes** - Fix crash when a `std::string` containing null-terminated characters is passed to the logger. ([#176](https://github.com/odygrd/quill/issues/176)) ## v2.0.1 **Improvements** - Add a flag to RotatingFileHandler to disable removing the old files when `w` mode is used. ## v2.0.0 From version `v2` and onwards only c++17 is supported. This version is a major refactor. **Fixes** - RotatingFileHandler will now correctly rotate the files when append mode is used ([#123](https://github.com/odygrd/quill/issues/123)) **Improvements** - Reduced and simplified codebase. - Improved backend worker thread performance. - `QUILL_DUAL_QUEUE_MODE` has been removed. A single queue now handles every case. - `QUILL_STRING` has been removed. That macro is no longer required when passing a format string to the PatternFormatter. **Differences** - `v1.7` compiles with c++14, `v2` only compiles for c++17. - `v1.7` on Windows supports wide character logging, `v2` has limited wide character support such as logging `wchar_t` , `std::wstring`, `std::wstring_view`. For example, logging `std::vector` is not supported. - `v1.7` on Windows requires the filepath used for the handlers as a wide strings, `v2` supports only filenames as narrow strings. ## v1.7.3 **Improvements/Fixes** - Fix crash on windows when a long wstring (>500 chars) is logged ([#173](https://github.com/odygrd/quill/issues/173)) - Fix compiler error when trying to compile with -DQUILL_DISABLE_NON_PREFIXED_MACROS ([#174](https://github.com/odygrd/quill/issues/174)) - Fix a compile warning in clang ([#175](https://github.com/odygrd/quill/issues/175)) ## v1.7.2 **Improvements/Fixes** - Fix compile error when C++20 is used on windows ([#162](https://github.com/odygrd/quill/issues/162)) ## v1.7.1 **Improvements/Fixes** - Fix support for wide characters on Windows ([#168](https://github.com/odygrd/quill/issues/168)) - Fix compilation error when `Quill::Logger*` is stored as a class member in templated classes - Add `FilenameAppend::DateTime` as an option when creating a file handler ## v1.7.0 **New Features** - Add a new function `quill::get_all_loggers()` that returns all the existing loggers. ([#114](https://github.com/odygrd/quill/issues/114)) - Add `%(level_id)` to pattern formatter. ([#136](https://github.com/odygrd/quill/issues/136)) - Users can now specialise `copy_loggable` to mark user defined types as safe to copy. ([#132](https://github.com/odygrd/quill/issues/132)) **Improvements/Fixes** - Fix initializations for C++17. - Fix compiler warning in `check_format()` function. - Replace `QUILL_DUAL_QUEUE_MODE` with `QUILL_DISABLE_DUAL_QUEUE_MODE`. - Update bundled fmt to 8.1.1 - Minor performance and accuracy improvements to rdtsc clock used by the backend thread. - Fix compile error when C++20 is used. ([#162](https://github.com/odygrd/quill/issues/162)) - Fix `get_page_size()` to only call sysconf once. ([#160](https://github.com/odygrd/quill/issues/160)) - Fix incorrect timestamps in the log file when the system clock is updated. ([#127](https://github.com/odygrd/quill/issues/127)) - Previously if `quill:start(true)` was called more than once in the application, the signal handlers would get initialised again. Now any subsequent calls to `quill:start(true)` will now have no effect ([#167](https://github.com/odygrd/quill/issues/167)) - Previously when the max limit of rotated files in `RotatingFileHandler` was reached, quill would stop rotating and instead keep logging everything into the last log file. Now when the maximum limit of files is reached, quill will now keep rotating by replacing the oldest logs. ([#157](https://github.com/odygrd/quill/issues/157)) - Improve the backend logging thread responsiveness when variables are logged in loops without any delay from multiple threads. ([#116](https://github.com/odygrd/quill/issues/116)) - Fix some undefined behaviour issues reported via the AddressSantizer on the backend logging thread. ([#166](https://github.com/odygrd/quill/issues/166)) ## v1.6.3 **Improvements/Fixes** - Add support for `%(thread_name)` in PatternFormatter. ([#97](https://github.com/odygrd/quill/issues/97)) - Add missing header needed for recent versions of fmt. ([#95](https://github.com/odygrd/quill/issues/95)) - Force flush all active handlers on application exit. - Update bundled fmt to 8.0.1 ## v1.6.2 **Fixes** - Fix WIN32 compilation error when `NOMINMAX` is already defined. - Fix `string` to `wstring` MinGW conversion. ([#92](https://github.com/odygrd/quill/issues/92)) - Log enums via the main queue. ([#90](https://github.com/odygrd/quill/issues/90)) - Fix windows compiler error when `min/max` macros are defined. ([#94](https://github.com/odygrd/quill/issues/94)) ## v1.6.1 **Improvements/Fixes** - Fix windows C++20 build. ([#83](https://github.com/odygrd/quill/issues/83)) - Fix ARM build on windows. - Fix `example_backtrace` and minor bug when destructing with empty backtrace. ## v1.6.0 **New Features** - Dual queue mode offering even lower latencies on hot paths. See [Dual Queue Mode](https://github.com/odygrd/quill/wiki/9.-Dual-Queue-Mode). - Added a signal handler for linux and windows. The signal handler flushes the log when the app crashes or exits. ([#1](https://github.com/odygrd/quill/issues/1)) - Added support for custom handlers. ([#75](https://github.com/odygrd/quill/issues/75)) - Quill now compiles and runs on Cygwin. **Improvements/Fixes** - The queue from the caller to the backend worker thread has been reworked. The new queue generates slightly better assembly than the previous one. Quill does no longer depend on mapping the same region of physical memory twice. - Replaced an assertion check that could trigger incorrectly. ([#68](https://github.com/odygrd/quill/issues/68)) - Fixed build on `ARM_ARCH < 6`. ([#78](https://github.com/odygrd/quill/issues/78)) - Fixed compile errors when `QUILL_NOEXCEPTIONS`, `CMAKE_CXX_STANDARD 20`, `QUILL_USE_BOUNDED_QUEUE` are set. - The unit tests have been moved to a separate binary with their own `main()`. This increased build times when building the tests, but the failures are now easier to debug on different CI platforms and the tests can also run faster in parallel. - Fixed minor compiler warnings on windows. - Upgraded bundled libfmt to `7.1.3` **Note** - If a custom queue capacity is defined using `#define QUILL_QUEUE_CAPACITY` after `1.6.0` the whole library needs to be recompiled. ## v1.5.2 - Removed the use of `fmt::format()` in `FileUtilities.cpp` as a workaround to the link errors in fmt v7. Use the header only version of libfmt when external libfmt is defiend is no longer required. ## v1.5.1 - When QUILL_FMT_EXTERNAL is defined, `quill` will use the header only version of `libfmt`. This is a workaround to the link errors after libftm v7 ## v1.5.0 - Upgraded bundled libfmt to `7.1.2` - Added `Filters`. The filter class can be used for filtering log records. Filters can be added to handler instances. See [example_filters.cpp](https://github.com/odygrd/quill/blob/master/examples/example_filters.cpp) - It is now possible to set the log level severity on the handler objects. See [example_filters.cpp](https://github.com/odygrd/quill/blob/master/examples/example_handler_log_levels.cpp) ([#49](https://github.com/odygrd/quill/issues/49)) - Timestamp formatting optimisation for the backend worker thread. - Free list allocator optimisation for the backend worker thread. - Fixed PatternFormatter ignoring a portion of the pattern was ignored, when no format specifiers were present. ([#56](https://github.com/odygrd/quill/issues/56)) - When `%(function_name)` is used in PatternFormatter the namespace delimiter is replaced from `::` to `.` (Windows only). ([#61](https://github.com/odygrd/quill/issues/61)) - Arguments passed to the logger are no longer being evaluated when the log statement is not logged. ([#67](https://github.com/odygrd/quill/issues/67)) - PatternFormatter enhancement. It is now possible to pass [{fmt} string syntax](https://fmt.dev/latest/syntax.html) to `QUILL_STRING`. The default PatternFormatter string has been changed to: `"%(ascii_time) [%(thread)] %(fileline:<28) LOG_%(level_name) %(logger_name:<12) - %(message)"`. This results to the following log being properly aligned despite the different lengths of each filename and logger name. ``` 22:31:07.995438465 [2666041] file1.h:11 LOG_INFO logger1 - Log from file. 22:31:07.995445699 [2666041] long_file2.h:11 LOG_INFO logger_fl2 - Log from other file. 22:31:07.995457144 [2666041] a_longer_file_3.hpp:11 LOG_INFO logger_fl2_l - Log from other file. 22:31:07.995462471 [2666041] example_trivial.cpp:30 LOG_TRACE_L3 root - This is a log trace l3 example 1 ``` ## v1.4.1 - Do not force `quill` to always build as `static` library in cmake. - Minor fix when `quill` is compiled with no exceptions. - Add the option to disable the non prefixed macro definitions if `QUILL_DISABLE_NON_PREFIXED_MACROS` is defined. ([#40](https://github.com/odygrd/quill/issues/40)) ## v1.4.0 - Added support for printing colour codes in the terminal. See [ConsoleHandler](https://github.com/odygrd/quill/wiki/2.-Handlers#consolehandler) - RotatingFileHandler improvements and minor change in API. See [RotatingFileHandler](https://github.com/odygrd/quill/wiki/2.-Handlers#rotatingfilehandler) - DailyFileHandler is removed and replaced by TimeRotatingFileHandler. See [TimeRotatingFileHandler](https://github.com/odygrd/quill/wiki/2.-Handlers#timerotatingfilehandler) - Added backtrace logging. Log messages can be stored in a buffer and flushed later on demand. See [Backtrace Logging](https://github.com/odygrd/quill/wiki/6.-Backtrace-Logging) - Added bundled `doctest` `2.4.0` - Migrated all tests from `gtest` to `doctest`. - Upgraded bundled libfmt to `7.0.3` ## v1.3.3 - Upgraded bundled libfmt to `7.0.2` - Fixed compile error with libfmt versions > `7.0.0` ## v1.3.2 - Add a CMake option `QUILL_USE_BOUNDED_QUEUE` for bounded queue. - Fixed a clang 10 warning - Fixed MinGw build ## v1.3.1 - Minor CMake fixes when `QUILL_FMT_EXTERNAL` option is used. ## v1.3.0 **New Features** - Added option `QUILL_NO_EXCEPTIONS` to disable exceptions, std::abort() is called instead of an exception. ([#16](https://github.com/odygrd/quill/issues/16)) - Exceptions thrown in the backend worker thread, will now call a user provided error handler callback to handle the error. ([#21](https://github.com/odygrd/quill/issues/21)) - Compile time checks for unsafe to copy user defined types. Non trivial user defined types must be explicitly tagged as safe to copy with the use of `QUILL_COPY_LOGGABLE;`. Otherwise they have to be formatted and passed as a string to the logger by the user. The old unsafe mode is still usable by `#define QUILL_MODE_UNSAFE` ([#20](https://github.com/odygrd/quill/issues/20)) - Added `QUILL_USE_BOUNDED_QUEUE`. In this mode no new queues get allocated but instead log messages get lost. Number of lost messages is reported to stderr. - Minor hot path optimisation. The pointer to the metadata for each log message is no logger copied to the queue but passed as a template argument instead. - Added a latency benchmark, easily extendable for any logger **Improvements/Fixes** - `QUILL_RDTSC_CLOCK` option is replaced by `QUILL_CHRONO_CLOCK` which is by OFF by default. - Improve compiler error message when trying to log a non copy constructible user defined type - Fix buffer reallocation bug on TimestampFormatter. In previous versions any timestamp format set to 'set_pattern' expanding to a string longer than 32 bytes would cause a crash. ([#24](https://github.com/odygrd/quill/issues/24)) - The backend logging thread will now copy all messages from the SPSC queue to a local priority queue. This keeps the SPSC less empty avoiding a potential allocation on the hot path. - `std::string_view` is now promoted to `std::string` to take a deep copy - The queue capacity has been moved from `config` to `Tweakme.h`. - Multiple formats patterns support for `stdout` and `stderr` handlers. See [example_stdout_multiple_formatters.cpp](https://github.com/odygrd/quill/blob/master/examples/example_custom_formatter.cpp) - `quill::start()` will now block until the backend worker has started. - Upgraded bundled libfmt to `6.2.1` ## v1.2.3 - CMake changes to support package installation in conan. ## v1.2.2 - Support for `arm/arm64`. ([#19](https://github.com/odygrd/quill/issues/19)) - Add a cmake option `QUILL_ENABLE_INSTALL` to enable cpack. ## v1.2.1 - Improved `QUILL_RDTSC_CLOCK` tweak option. It is now possible to switch between using `rdtsc` or `std::chrono` clock without having to recompile quill as library. ## v1.2.0 - Linking and including an external version of `fmt` is now supported. See `TweakMe.h` - Fixed compiler warnings when using clang's `-Wdocumentation`. ([#12](https://github.com/odygrd/quill/issues/12)) - Fixed a bug that wouldn't report a compile-time error for invalid format strings. ([#13](https://github.com/odygrd/quill/issues/13)) - Added process ID to Formatter. ([#14](https://github.com/odygrd/quill/issues/14)) - Enhanced timestamp formatting. The `timestamp_format` string passed in `handler->set_pattern(format_pattern, timestamp_format, timezone)` now accepts three additional specifiers `%Qms` , `%Qus`, `%Qus` that can be used to format the fractional seconds. See [here](https://github.com/odygrd/quill/wiki/3.-Formatters). ([#15](https://github.com/odygrd/quill/issues/15)) ## v1.1.0 - Daily file handler. The file handler rollover every 24 hours - Rotating file handler. The file handler will rollover based on the size of the file - MinGW compatibility - Added a CMake option `QUILL_VERBOSE_MAKEFILE`. Building Quill as a master project now defaults to non verbose makefile output unless `-DQUILL_VERBOSE_MAKEFILE=ON` is passed to CMake. ([#6](https://github.com/odygrd/quill/issues/6)) - Flush policy improvement. Previously Quill backend worker thread would never `flush`. This made watching the live log of the application harder because the user has to wait for the operating system to flush or `quill::flush()` had to be called on the caller threads. This has now been fixed, when the backend thread worker has no more log messages to process it will automatically `flush`. ([#8](https://github.com/odygrd/quill/issues/8)) - The log level names have been changed from `"LOG_INFO"`, `"LOG_DEBUG"`, etc to `"INFO"`, `"DEBUG"`, etc .. The default formatter string is now using `"LOG_"%(level_name)` instead of `%(level_name)` therefore there is now change in the behaviour. This change gives a lot of more flexibility to users who prefer to see e.g. `INFO` instead of `LOG_INFO` in the logs. ([#7](https://github.com/odygrd/quill/issues/7)) - An option has been added to append the date to the filename when using a FileHandler `quill::file_handler(filename, mode, FilenameAppend);`. ([#7](https://github.com/odygrd/quill/issues/7)) - It is now possible to specify the timezone of each handler timestamp. A new parameter is added to `file_handler->set_pattern(...)`. See `PatternFormatter::Timezone` . ([#7](https://github.com/odygrd/quill/issues/7)) - Rename `emit` as it can conflict with Qt macros. ([#4](https://github.com/odygrd/quill/issues/4)) - Upgraded `libfmt` to `6.2.0`. ## v1.0.0 - Initial release. - Using `libfmt` to `6.1.2`. quill-12.1.0/CLAUDE.md000066400000000000000000000220371522564103500142070ustar00rootroot00000000000000# CLAUDE.md ## Project Summary Quill is a C++17 asynchronous low-latency logging library. Main design goals: - keep frontend logging overhead as low as possible, - move formatting and I/O to a backend worker thread, - preserve timestamp ordering across threads, - provide a practical API without compromising hot-path performance. The project is performance-sensitive. Many design choices prioritize low frontend latency over extra convenience or extra validation at every call site. ## Repository Shape Important directories: - `include/quill/`: public headers and most implementation. - `docs/`: Sphinx docs and API guidance. - `test/unit_tests/`: focused component tests. - `test/integration_tests/`: end-to-end behavioral tests. - `examples/`: usage examples. - `benchmarks/`: compile-time and runtime benchmarks. ## Core Architecture The library has two main parts: 1. Frontend - User threads log via macros or macro-free APIs. - Each thread writes into its own thread-local SPSC queue. - The hot path serializes arguments and stores metadata references. 2. Backend - A single backend worker thread polls frontend queues. - It orders events by timestamp. - It performs formatting and sink I/O. When reviewing or changing code, always ask: - Is this on the frontend hot path or backend path? - Does this add cost to every log statement? - Does this move work from backend to frontend? - Does this change a documented user contract? - Before fixing a "bug", trace all call sites — the invariant may be maintained by callers rather than the function itself. ## Important Contracts - Single backend worker thread. - `Logger` objects are thread-safe for logging. - Logger configuration is effectively immutable after creation; recreate a logger instead of mutating it in place. - `Frontend::remove_logger_blocking()` must only be used while the backend is running. - Once a logger is removed, that `Logger*` must not be used again. - Removing the same logger from multiple threads is unsupported. - The project supports both exception and no-exception builds. - Ideally used as a static library, but some users integrate it through shared-library / `.so` boundaries. Keep shared-library pitfalls in mind as well, especially singleton lifetime, duplicated state across DSOs, symbol visibility, and shutdown behavior. - If you change public behavior, keep headers, docs, tests, and changelog aligned. ## Layering Respect the library layering: - Avoid introducing dependencies from lower-level code to higher-level code. - Flag dependency inversions in reviews. - `quill/core` is part of the frontend-facing surface and should remain self-contained: it may depend on `quill/core` and `quill/bundled`, but not on other layers. - For normal user-side logging, the intended lightweight include surface is `quill/Logger.h` and `quill/LogMacros.h`. Be very careful with every include reachable from those headers, including standard library headers. Any extra `#include` there propagates into user translation units and increases compile-time cost and header pollution. ## Updating Bundled libfmt The bundled fmt copy under `include/quill/bundled/fmt/` is vendored source with Quill-local patches. Treat each upgrade as two separate jobs: first identify the upstream delta, then port the Quill-specific changes. - Identify the current bundled fmt version from `FMTQUILL_VERSION` in `include/quill/bundled/fmt/base.h`; the value uses fmt's `major * 10000 + minor * 100 + patch` encoding. Pick the target version from the official fmt releases at https://github.com/fmtlib/fmt/releases. - Download and unpack the official current and target fmt release archives outside `include/quill/bundled/fmt/`. Compare the official current release with Quill's bundled tree to find local patches, then compare the target release with the official current release to understand upstream changes. - Replace the vendored fmt files from the official target release, then run: `python3 scripts/rename_libfmt.py include/quill/bundled/fmt FMTQUILL fmtquill` - Preserve upstream formatting in bundled fmt files. Do not run clang-format or broad formatting tools over vendored fmt; port Quill patches as the smallest necessary edits. - Reapply and re-check Quill-local changes that still apply to the target fmt version: - In `base.h`, force header-only mode with `FMTQUILL_HEADER_ONLY`. - In `base.h`, keep the end-of-file `format.h` include removed or disabled when it is only included because `FMTQUILL_HEADER_ONLY` is set. - Keep the buffer `append` fast path that uses `memcpy(ptr_ + size_, begin, count * sizeof(T))` when `std::is_same::value`, with the element-wise copy fallback when the types differ. - In `chrono.h`, keep the `std::micro` suffix as `"us"` unless upstream already matches that behavior. - In `format.h`, retain only the warning suppressions still needed by supported compilers, such as GCC/Clang `-Wfloat-equal` and GCC `-Wstringop-overflow` false positives. - Keep `is_fast_float::value` in places where supported compilers require the type-trait form; if upstream changes this code, confirm with a targeted compile instead of applying a blind search-and-replace. - Search the previous local diff for any other Quill-specific compiler workarounds, diagnostics, ABI/header-only changes, namespace changes, or performance fixes and port the ones that remain applicable. - After porting, inspect the diff to confirm it contains only the upstream fmt update plus intentional Quill-local patches, then run the narrowest relevant build or test target for the touched code. ## Documentation - The Sphinx docs live under `docs/`. - Any standalone runnable sample in a `.rst` file (anything with `main()`, a class definition, or that the reader could copy-paste and compile as-is) MUST live in its own compilable `.cpp` file under `docs/snippets/`, added to `docs/snippets/CMakeLists.txt`, and referenced from the `.rst` via `.. literalinclude:: snippets/.cpp`. Never write full examples as inline `.. code-block:: cpp` blocks — CI must be able to compile them so they cannot silently drift from the real API. - When adding a new docs page with a runnable sample, create the snippet file first, confirm it builds under `QUILL_BUILD_EXAMPLES=ON`, and only then wire it into the `.rst` with a `literalinclude` directive. - Short illustrative fragments (a macro call, a function signature, a few lines showing an API shape) can stay as inline `.. code-block:: cpp` since they are not standalone programs. ## Testing - Each new feature or fix should have a corresponding test, either a unit test or a regression/integration test. - Sometimes consider extending an existing test with one more assertion or log statement instead of adding a new one. - Unit test files may contain multiple `TEST_CASE`s when the scenarios are closely related. - Each integration test file should contain exactly one `TEST_CASE`. - Integration/regression test files should be self-contained. Do not add shared helper headers for them; keep any test-only setup local to the `.cpp` file even if that means a small amount of duplication. - Integration tests must use unique logger names, test names, and log/output filenames so they can run safely in parallel without colliding through shared files or global state. - For conditionally-skipped tests (platform-specific, `QUILL_NO_EXCEPTIONS`, etc.), keep the `TEST_CASE` itself unguarded and put the `#if` inside the test body. On unsupported configurations, return early from the test instead of wrapping the whole test declaration in preprocessor guards. - If the behavior is user-visible or easy to regress, prefer an end-to-end test in addition to a narrow unit test. - New features and tests should compile and run across supported platforms and toolchains, including Linux, macOS, and Windows, and major compilers such as GCC, Clang, and Intel LLVM. - Never attempt a full build of all targets unless the user explicitly asks for one. Full builds are slow on this project, so only build the specific target(s) touched by the change (e.g. a single snippet, unit test, or integration test) and let the user drive any broader build. ## Code Style - The repo is C++17 only. - Follow existing codebase patterns. - Prefer readable, maintainable, low-overhead code. - Use descriptive names. - Prefer const-correctness, `constexpr`, and RAII where appropriate. - Use `auto` when it improves readability, not by default everywhere. - Prefer brace initialization for variables and objects instead of `=` or `()` where it is valid and readable. - Always use braces for control flow. - Place member variables at the end of the class definition. - Keep comments concise and useful; follow the existing Doxygen style in headers. ## Performance Mindset - Never assume an optimization helps; use `perf` or assembly output to validate. - Watch unnecessary allocations, cache locality, vectorization hints, and false sharing. - Consider the performance impact of every change, especially on the frontend where even a single extra branch can matter. The backend is less sensitive, but throughput still matters. quill-12.1.0/CMakeLists.txt000066400000000000000000000522221522564103500154670ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.12...4.0) project(quill) #------------------------------------------------------------------------------------------------------- # Options #------------------------------------------------------------------------------------------------------- option(QUILL_NO_EXCEPTIONS "Enable this option to build without exception handling support." OFF) option(QUILL_NO_THREAD_NAME_SUPPORT "Enable this option to disable features that require thread name retrieval, ensuring compatibility with older Windows versions (e.g., Windows Server 2012/2016) and Android." OFF) option(QUILL_USE_SEQUENTIAL_THREAD_ID "Enable this option to use a sequential counter for thread IDs instead of OS-assigned thread IDs. Requires defining QUILL_DEFINE_SEQUENTIAL_THREAD_ID (from quill/Utility.h) in exactly one translation unit." OFF) option(QUILL_X86ARCH "Enable x86-specific optimizations for cache coherence using _mm_prefetch, _mm_clflush, and _mm_clflushopt instructions. Ensure the target architecture must also be specified with -march=\"...\" when enabling this option." OFF) option(QUILL_DISABLE_NON_PREFIXED_MACROS "Enable this option to disable non-prefixed `LOG_*` macros, keeping only the `QUILL_LOG_*` macros to avoid conflicts with other logging libraries." OFF) option(QUILL_DISABLE_FUNCTION_NAME "Disable the use of __FUNCTION__ in `LOG_*` macros when the function name is not needed." OFF) option(QUILL_DETAILED_FUNCTION_NAME "Use detailed function name (__PRETTY_FUNCTION__ or __FUNCSIG__) instead of __FUNCTION__ in LOG_* macros" OFF) option(QUILL_DISABLE_FILE_INFO "Disable the use of __FILE__ and __LINE__ in `LOG_*` macros when the file name and the line number are not needed." OFF) option(QUILL_ENABLE_ASSERTIONS "Enable assertions in release builds. When disabled, assertions are only active in debug builds." OFF) option(QUILL_BUILD_EXAMPLES "Enable this option to build and install the examples. Set this to ON to include example projects in the build process and have them installed after configuring with CMake." OFF) option(QUILL_BUILD_MODULE "Enable this option to build the experimental C++20 named module target." OFF) option(QUILL_BUILD_EXAMPLE_PROMETHEUS "Build the prometheus-cpp metric publishing example. Requires prometheus-cpp to be installed and findable via CMAKE_PREFIX_PATH." OFF) option(QUILL_BUILD_TESTS "Enable this option to build the test suite." OFF) option(QUILL_ENABLE_EXTENSIVE_TESTS "Enable extensive tests that may require more resources and are not suitable for hosted CI runners." OFF) option(QUILL_BUILD_BENCHMARKS "Enable this option to build the benchmarks." OFF) option(QUILL_SANITIZE_ADDRESS "Enable AddressSanitizer (ASan) for memory error detection in tests." OFF) option(QUILL_SANITIZE_THREAD "Enable ThreadSanitizer (TSan) for detecting thread-related issues in tests. Note: Using this option with non-Clang compilers may produce false positives." OFF) option(QUILL_BUILD_FUZZING "Enable fuzzing with libFuzzer, AddressSanitizer, and UndefinedBehaviorSanitizer. Requires Clang compiler." OFF) option(QUILL_CODE_COVERAGE "Enable code coverage analysis during the build." OFF) option(QUILL_USE_VALGRIND "Use Valgrind as the default memory checking tool in CTest. Valgrind must be installed." OFF) option(QUILL_ENABLE_INSTALL "Enable the CMake install target when Quill is not the master project." OFF) option(QUILL_DOCS_GEN "Generate documentation during the build process." OFF) option(QUILL_ENABLE_TIME_TRACE "Enable -ftime-trace to generate compile-time profiling data. Requires Clang." OFF) # Internal option set(QUILL_ENABLE_GCC_HARDENING OFF CACHE INTERNAL "") #------------------------------------------------------------------------------------------------------- # Determine if quill is built as a subproject (using add_subdirectory) or if it is the master project. #------------------------------------------------------------------------------------------------------- set(QUILL_MASTER_PROJECT FALSE CACHE BOOL "Master Project" FORCE) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(QUILL_MASTER_PROJECT TRUE CACHE BOOL "Master Project" FORCE) endif () #------------------------------------------------------------------------------------------------------- # Custom cmake functions #------------------------------------------------------------------------------------------------------- set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) include(QuillUtils) #------------------------------------------------------------------------------------------------------- # Resolve version #------------------------------------------------------------------------------------------------------- quill_extract_version() project(quill VERSION ${QUILL_VERSION} LANGUAGES CXX) #------------------------------------------------------------------------------------------------------- # Set default build to release #------------------------------------------------------------------------------------------------------- if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build" FORCE) endif () #--------------------------------------------------------------------------------------- # Compiler config #--------------------------------------------------------------------------------------- if (NOT CMAKE_CXX_STANDARD) # If CMAKE_CXX_STANDARD is not set, configure it to 17 by default set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) elseif (CMAKE_CXX_STANDARD LESS 17) # If CMAKE_CXX_STANDARD is set but less than 17, issue a fatal error message(FATAL_ERROR "Quill requires at least C++17. Please set CMAKE_CXX_STANDARD to 17 or higher.") endif () #------------------------------------------------------------------------------------------------------- # Required Packages #------------------------------------------------------------------------------------------------------- find_package(Threads REQUIRED) if (QUILL_BUILD_TESTS) enable_testing() if (QUILL_USE_VALGRIND) # find valgrind find_program(MEMORYCHECK_COMMAND NAMES valgrind) if (NOT MEMORYCHECK_COMMAND) message(WARNING "Valgrind not found") endif () # set valgrind params set(MEMORYCHECK_COMMAND_OPTIONS "--tool=memcheck --leak-check=full --leak-resolution=med --show-leak-kinds=all --track-origins=yes --vgdb=no --fair-sched=yes") # add memcheck test action to ctest include(CTest) endif () endif () # Error out if QUILL_ENABLE_EXTENSIVE_TESTS is ON but QUILL_BUILD_TESTS is OFF if (QUILL_ENABLE_EXTENSIVE_TESTS AND NOT QUILL_BUILD_TESTS) message(FATAL_ERROR "QUILL_ENABLE_EXTENSIVE_TESTS requires QUILL_BUILD_TESTS to be enabled. Please enable QUILL_BUILD_TESTS.") endif () #------------------------------------------------------------------------------------------------------- # Log Info #------------------------------------------------------------------------------------------------------- if (QUILL_MASTER_PROJECT) option(QUILL_VERBOSE_MAKEFILE "Enable verbose output for makefiles when Quill is the master project. This provides detailed information about the build process." OFF) message(STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE}) message(STATUS "QUILL_VERSION: ${QUILL_VERSION}") endif () message(STATUS "QUILL_NO_EXCEPTIONS: " ${QUILL_NO_EXCEPTIONS}) message(STATUS "QUILL_NO_THREAD_NAME_SUPPORT: " ${QUILL_NO_THREAD_NAME_SUPPORT}) message(STATUS "QUILL_USE_SEQUENTIAL_THREAD_ID: " ${QUILL_USE_SEQUENTIAL_THREAD_ID}) message(STATUS "QUILL_X86ARCH: " ${QUILL_X86ARCH}) message(STATUS "QUILL_DISABLE_NON_PREFIXED_MACROS: " ${QUILL_DISABLE_NON_PREFIXED_MACROS}) message(STATUS "QUILL_DISABLE_FUNCTION_NAME: " ${QUILL_DISABLE_FUNCTION_NAME}) message(STATUS "QUILL_DETAILED_FUNCTION_NAME: " ${QUILL_DETAILED_FUNCTION_NAME}) message(STATUS "QUILL_DISABLE_FILE_INFO: " ${QUILL_DISABLE_FILE_INFO}) message(STATUS "QUILL_ENABLE_ASSERTIONS: " ${QUILL_ENABLE_ASSERTIONS}) message(STATUS "QUILL_ENABLE_INSTALL: " ${QUILL_ENABLE_INSTALL}) message(STATUS "QUILL_BUILD_MODULE: " ${QUILL_BUILD_MODULE}) #--------------------------------------------------------------------------------------- # Verbose make file option #--------------------------------------------------------------------------------------- if (QUILL_VERBOSE_MAKEFILE) set(CMAKE_VERBOSE_MAKEFILE TRUE CACHE BOOL "Verbose output" FORCE) endif () # Strip MSVC default /EHsc when building without exceptions so that /EHs-c- is not # silently overridden. Must happen at directory scope; doing this inside a function # would be a no-op because CMAKE_CXX_FLAGS assignments would not escape the function. if (QUILL_NO_EXCEPTIONS AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif () # address sanitizer flags if (QUILL_SANITIZE_ADDRESS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer -g") endif () # thread sanitizer flags if (QUILL_SANITIZE_THREAD) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer -g") endif () # Append extra options for coverage if (QUILL_CODE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -fno-omit-frame-pointer -g -fprofile-arcs -ftest-coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") endif () # Clang -ftime-trace for compile-time profiling if (QUILL_ENABLE_TIME_TRACE) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftime-trace") else () message(WARNING "QUILL_ENABLE_TIME_TRACE is only supported with Clang. Ignoring.") endif () endif () if (QUILL_BUILD_BENCHMARKS) add_subdirectory(benchmarks) endif () if (QUILL_BUILD_TESTS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test) add_subdirectory(test) endif () if (QUILL_BUILD_FUZZING) if (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(FATAL_ERROR "QUILL_BUILD_FUZZING requires Clang compiler") endif () add_subdirectory(fuzz) endif () # library name set(TARGET_NAME quill) # header files set(HEADER_FILES include/quill/backend/BackendManager.h include/quill/backend/BackendMdcState.h include/quill/backend/BackendOptions.h include/quill/backend/BackendWorker.h include/quill/backend/BackendWorkerLock.h include/quill/backend/BacktraceStorage.h include/quill/backend/ManualBackendWorker.h include/quill/backend/PatternFormatter.h include/quill/backend/RdtscClock.h include/quill/backend/SignalHandler.h include/quill/backend/StringFromTime.h include/quill/backend/ThreadUtilities.h include/quill/backend/TimestampFormatter.h include/quill/backend/TransitEvent.h include/quill/backend/TransitEventBuffer.h include/quill/backend/BackendUtilities.h include/quill/bundled/fmt/args.h include/quill/bundled/fmt/base.h include/quill/bundled/fmt/chrono.h include/quill/bundled/fmt/color.h include/quill/bundled/fmt/compile.h include/quill/bundled/fmt/format.h include/quill/bundled/fmt/format-inl.h include/quill/bundled/fmt/os.h include/quill/bundled/fmt/ostream.h include/quill/bundled/fmt/printf.h include/quill/bundled/fmt/ranges.h include/quill/bundled/fmt/std.h include/quill/bundled/fmt/xchar.h include/quill/core/Attributes.h include/quill/core/BoundedSPSCQueue.h include/quill/core/ChronoTimeUtils.h include/quill/core/Common.h include/quill/core/DynamicFormatArgStore.h include/quill/core/Codec.h include/quill/core/Filesystem.h include/quill/core/FrontendOptions.h include/quill/core/InlinedVector.h include/quill/core/LoggerBase.h include/quill/core/LoggerManager.h include/quill/core/LogLevel.h include/quill/core/MacroMetadata.h include/quill/core/MathUtilities.h include/quill/core/Metric.h include/quill/core/MetricManager.h include/quill/core/PatternFormatterOptions.h include/quill/core/QuillError.h include/quill/core/Rdtsc.h include/quill/core/SinkManager.h include/quill/core/SourceLocation.h include/quill/core/Spinlock.h include/quill/core/ThreadContextManager.h include/quill/core/ThreadPrimitives.h include/quill/core/TimeUtilities.h include/quill/core/UnboundedSPSCQueue.h include/quill/backend/Utf8Conv.h include/quill/filters/Filter.h include/quill/sinks/AndroidSink.h include/quill/sinks/ConsoleSink.h include/quill/sinks/FileSink.h include/quill/sinks/JsonSink.h include/quill/sinks/NullSink.h include/quill/sinks/metrics/PrometheusSink.h include/quill/sinks/RotatingFileSink.h include/quill/sinks/RotatingJsonFileSink.h include/quill/sinks/RotatingSink.h include/quill/sinks/Sink.h include/quill/sinks/StreamSink.h include/quill/sinks/SyslogSink.h include/quill/sinks/SystemdSink.h include/quill/std/Array.h include/quill/std/Bitset.h include/quill/std/Chrono.h include/quill/std/Complex.h include/quill/std/Deque.h include/quill/std/FilesystemPath.h include/quill/std/ForwardList.h include/quill/std/List.h include/quill/std/Map.h include/quill/std/Optional.h include/quill/std/Pair.h include/quill/std/Set.h include/quill/std/SystemError.h include/quill/std/Tuple.h include/quill/std/UnorderedMap.h include/quill/std/UnorderedSet.h include/quill/std/Variant.h include/quill/std/Vector.h include/quill/std/WideString.h include/quill/Backend.h include/quill/BackendTscClock.h include/quill/BinaryDataDeferredFormatCodec.h include/quill/CsvWriter.h include/quill/DeferredFormatCodec.h include/quill/DirectFormatCodec.h include/quill/Frontend.h include/quill/HelperMacros.h include/quill/LogFunctions.h include/quill/Logger.h include/quill/LogMacros.h include/quill/SimpleSetup.h include/quill/StopWatch.h include/quill/StringRef.h include/quill/UserClockSource.h include/quill/Utility.h ) # Add as a library add_library(${TARGET_NAME} INTERFACE) add_library(${TARGET_NAME}::${TARGET_NAME} ALIAS ${TARGET_NAME}) if (QUILL_NO_EXCEPTIONS) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_NO_EXCEPTIONS) endif () if (QUILL_NO_THREAD_NAME_SUPPORT) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_NO_THREAD_NAME_SUPPORT) endif () if (QUILL_USE_SEQUENTIAL_THREAD_ID) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_USE_SEQUENTIAL_THREAD_ID) endif () if (QUILL_X86ARCH) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_X86ARCH) endif () if (QUILL_DISABLE_NON_PREFIXED_MACROS) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_DISABLE_NON_PREFIXED_MACROS) endif () if (QUILL_DISABLE_FUNCTION_NAME) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_DISABLE_FUNCTION_NAME) endif () if (QUILL_DETAILED_FUNCTION_NAME) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_DETAILED_FUNCTION_NAME) endif () if (QUILL_DISABLE_FILE_INFO) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_DISABLE_FILE_INFO) endif () if (QUILL_ENABLE_ASSERTIONS) target_compile_definitions(${TARGET_NAME} INTERFACE -DQUILL_ENABLE_ASSERTIONS) endif () if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.19) # cmake prior to 3.19 does not support target_sources for interface libraries target_sources(${TARGET_NAME} PRIVATE ${HEADER_FILES}) endif () # Link dependencies target_link_libraries(${TARGET_NAME} INTERFACE Threads::Threads) if (MINGW) # strftime requires this when using MinGw to correctly format the time .. target_link_libraries(${TARGET_NAME} INTERFACE ucrtbase) endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) target_link_libraries(${TARGET_NAME} INTERFACE stdc++fs) endif () # Add include directories for this library target_include_directories(${TARGET_NAME} INTERFACE $ $) # Compiler options target_compile_options(${TARGET_NAME} INTERFACE $<$,$>:-Wno-gnu-zero-variadic-macro-arguments>) if (QUILL_BUILD_MODULE) if (CMAKE_VERSION VERSION_LESS 3.28) message(FATAL_ERROR "QUILL_BUILD_MODULE requires CMake 3.28 or newer.") endif () if (CMAKE_CXX_STANDARD LESS 20) message(FATAL_ERROR "QUILL_BUILD_MODULE requires CMAKE_CXX_STANDARD to be 20 or higher.") endif () add_library(quill_module) add_library(quill::quill_module ALIAS quill_module) target_sources(quill_module PUBLIC FILE_SET CXX_MODULES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES src/quill.cc) target_link_libraries(quill_module PUBLIC ${TARGET_NAME}) target_compile_features(quill_module PUBLIC cxx_std_20) set_target_properties(quill_module PROPERTIES CXX_SCAN_FOR_MODULES ON) endif () if (QUILL_BUILD_EXAMPLES) add_subdirectory(examples) add_subdirectory(docs/snippets) endif () # Install if (QUILL_MASTER_PROJECT OR QUILL_ENABLE_INSTALL) # ---- Install ---- # include(GNUInstallDirs) include(CMakePackageConfigHelpers) set(version_config ${PROJECT_BINARY_DIR}/quill-config-version.cmake) set(project_config ${PROJECT_BINARY_DIR}/quill-config.cmake) set(pkgconfig ${PROJECT_BINARY_DIR}/quill.pc) set(targets_export_name quill-targets) set(QUILL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/quill CACHE STRING "Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.") set(QUILL_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING "Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.") set(QUILL_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING "Installation directory for include files, relative to ${CMAKE_INSTALL_PREFIX}.") set(QUILL_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH "Installation directory for pkgconfig (.pc) files, relative to ${CMAKE_INSTALL_PREFIX}.") # Use the thread lib flag that find_package(Threads) resolved for this platform # (e.g. -pthread on FreeBSD, -lpthread on older Linux, empty where pthread is in libc). if (WIN32) set(QUILL_PTHREAD_LIBS "") else () set(QUILL_PTHREAD_LIBS "${CMAKE_THREAD_LIBS_INIT}") endif () # Generate pkgconfig configure_file( "${CMAKE_CURRENT_LIST_DIR}/cmake/quill.pc.in" "${pkgconfig}" @ONLY) # Copy pkgconfig install(FILES "${pkgconfig}" DESTINATION "${QUILL_PKGCONFIG_DIR}") # Generate the version, config and target files into the build directory. write_basic_package_version_file( ${version_config} VERSION ${QUILL_VERSION} COMPATIBILITY AnyNewerVersion) configure_package_config_file( ${CMAKE_CURRENT_LIST_DIR}/cmake/quill-config.cmake.in ${project_config} INSTALL_DESTINATION ${QUILL_CMAKE_DIR}) # Install version, config files install(FILES ${project_config} ${version_config} DESTINATION ${QUILL_CMAKE_DIR}) # Install the headers install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/quill DESTINATION ${QUILL_INC_DIR}) # Install the library install(TARGETS ${TARGET_NAME} EXPORT ${targets_export_name} LIBRARY DESTINATION ${QUILL_LIB_DIR} ARCHIVE DESTINATION ${QUILL_LIB_DIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) # Export the library install(EXPORT ${targets_export_name} DESTINATION ${QUILL_CMAKE_DIR} NAMESPACE quill::) # ---- Packaging ---- # set(CPACK_GENERATOR ZIP) set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR}" "${PROJECT_NAME}" ALL .) set(CPACK_PROJECT_URL "https://github.com/odygrd/quill") set(CPACK_PACKAGE_VENDOR "Odysseas Georgoudis") set(CPACK_PACKAGE_CONTACT "Odysseas Odysseas ") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Asynchronous Low Latency C++ Logging Library") set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) set(CPACK_PACKAGE_RELOCATABLE ON) set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_RPM_PACKAGE_GROUP "System Environment/Libraries") set(CPACK_RPM_PACKAGE_URL ${CPACK_PROJECT_URL}) set(CPACK_RPM_PACKAGE_DESCRIPTION "Asynchronous Low Latency C++ Logging Library") include(CPack) endif () if (QUILL_DOCS_GEN) if (NOT QUILL_BUILD_EXAMPLES) message(FATAL_ERROR "QUILL_DOCS_GEN requires QUILL_BUILD_EXAMPLES to be ON. Please enable QUILL_BUILD_EXAMPLES.") endif () add_subdirectory(docs) endif () quill-12.1.0/LICENSE000066400000000000000000000020771522564103500137370ustar00rootroot00000000000000MIT License Copyright (c) 2020 - present, Odysseas Georgoudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. quill-12.1.0/MODULE.bazel000066400000000000000000000002661522564103500147340ustar00rootroot00000000000000module( name = "quill", version = "12.1.0", compatibility_level = 1, ) bazel_dep(name = "platforms", version = "0.0.11") bazel_dep(name = "rules_cc", version = "0.1.1") quill-12.1.0/README.md000066400000000000000000001214011522564103500142020ustar00rootroot00000000000000 --- ## 🧭 Table of Contents - [Introduction](#-introduction) - [Quick Start](#-quick-start) - [Features](#-features) - [Performance](#-performance) - [Usage](#-usage) - [Design](#-design) - [Caveats](#-caveats) - [License](#-license) --- ## ✨ Introduction **Quill** is a **high-performance asynchronous logging library** written in **C++**. It is designed for low-latency, performance-critical applications where every microsecond counts. - **Performance-Focused**: Quill consistently outperforms many popular logging libraries. - **Feature-Rich**: Packed with advanced features to meet diverse logging needs. - **Metric Publishing**: Publish pre-registered metric samples to Prometheus, StatsD, OpenTelemetry, or any in-process collector through the same asynchronous backend used for logs. See the [Metrics guide](https://quillcpp.readthedocs.io/en/latest/metrics.html). - **Battle-Tested**: Proven in demanding production environments. Extensively tested with sanitizers (ASan, UBSan, LSan) and fuzzed across a wide range of inputs. - **Extensive Documentation**: Comprehensive guides and examples available. - **Community-Driven**: Open to contributions, feedback, and feature requests. Try it on [Compiler Explorer](https://godbolt.org/z/n68asK7bY) --- ## ⩠Quick Start Getting started is easy and straightforward. Follow these steps to integrate the library into your project: ### Installation You can install Quill using the package manager of your choice: | Package Manager | Installation Command | |:---------------:|:----------------------------------------------:| | vcpkg | `vcpkg install quill` | | Conan | `conan install quill` | | Homebrew | `brew install quill` | | Meson WrapDB | `meson wrap install quill` | | Conda | `conda install -c conda-forge quill` | | Bzlmod | `bazel_dep(name = "quill", version = "x.y.z")` | | xmake | `xrepo install quill` | | nix | `nix-shell -p quill-log` | | build2 | `libquill` | ### Setup #### Quickest Setup For the shortest path from zero to working logs, use `simple_logger()`: ```c++ #include "quill/SimpleSetup.h" #include "quill/LogMacros.h" int main() { // log to the console auto* logger = quill::simple_logger(); LOG_INFO(logger, "Hello from {}!", "Quill"); // log to a file auto* logger2 = quill::simple_logger("test.log"); LOG_WARNING(logger2, "This message goes to a file"); } ``` **Console output:** ``` 20:07:18.423476231 [48917] main.cpp:8 LOG_INFO Hello from Quill! ``` #### Detailed Setup If you want explicit control over backend options, logger names, sinks, or formatters, use the `Backend` and `Frontend` APIs directly: ```c++ #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/Logger.h" #include "quill/sinks/ConsoleSink.h" #include int main() { quill::Backend::start(); quill::Logger* logger = quill::Frontend::create_or_get_logger( "root", quill::Frontend::create_or_get_sink("sink_id_1")); LOG_INFO(logger, "Hello from {}!", std::string_view{"Quill"}); } ``` **Output:** ``` 20:07:18.423476231 [48917] main.cpp:15 LOG_INFO root Hello from Quill! ``` You can also use the macro-free mode. The macro API (`LOG_INFO`) is the lowest-latency path. The function API (`quill::info`) reads more like ordinary code but is slightly slower. See [here](https://quillcpp.readthedocs.io/en/latest/macro_free_mode.html) for the trade-offs. ```c++ #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogFunctions.h" #include "quill/Logger.h" #include "quill/sinks/ConsoleSink.h" #include int main() { quill::Backend::start(); quill::Logger* logger = quill::Frontend::create_or_get_logger( "root", quill::Frontend::create_or_get_sink("sink_id_1")); quill::info(logger, "Hello from {}!", std::string_view{"Quill"}); } ``` ### Publishing Metrics Register `MetricMetadata` once, then publish `double` samples from hot threads through the same asynchronous backend used for logs. The bundled `PrometheusSink` handles counters, gauges, histograms, and summaries; custom sinks can route samples to StatsD, OpenTelemetry, or any in-process collector via `Sink::write_metric()`. ```c++ // One-time registration — returns a stable pointer valid for program lifetime. quill::MetricMetadata const* requests_total = quill::Frontend::create_metric( "requests_total_post_200", "requests_total", {{"method", "POST"}, {"status", "200"}}); // Hot path — no label serialization, just a pointer and a double. logger->publish_metric(requests_total, 1.0); ``` See the [Metrics guide](https://quillcpp.readthedocs.io/en/latest/metrics.html) for sink setup, custom sinks, and Prometheus integration. --- ## 🎯 Features - **High-Performance**: Ultra-low latency performance. - **Asynchronous Processing**: Background thread handles formatting and I/O, keeping your main thread responsive. - **Metric Publishing**: Publish pre-registered metric samples to Prometheus, StatsD, OpenTelemetry, or any in-process collector through the same asynchronous backend. See [Metrics](https://quillcpp.readthedocs.io/en/latest/metrics.html). - **Minimal Header Includes**: - **Frontend**: Only `Logger.h` and `LogMacros.h` needed for logging. Lightweight with minimal dependencies. - **Backend**: Single `.cpp` file inclusion. No backend code injection into other translation units. - **Compile-Time Optimization**: Eliminate specific log levels at compile time. - **Custom Formatters**: Define your own log output patterns. See [Formatters](https://quillcpp.readthedocs.io/en/latest/formatters.html). - **Timestamp-Ordered Logs**: Simplify debugging of multithreaded applications with chronologically ordered logs. - **Flexible Timestamps**: Support for `rdtsc`, `chrono`, or `custom clocks` - ideal for simulations and more. - **Backtrace Logging**: Store messages in a ring buffer for on-demand display. See [Backtrace Logging](https://quillcpp.readthedocs.io/en/latest/backtrace_logging.html) - **Multiple Output Sinks**: Console (with color), files (with rotation), JSON, ability to create custom sinks and more. - **Log Filtering**: Process only relevant messages. See [Filters](https://quillcpp.readthedocs.io/en/latest/filters.html). - **JSON Logging**: Structured log output. See [JSON Logging](https://quillcpp.readthedocs.io/en/latest/json_logging.html) - **Mapped Diagnostic Context (MDC)**: Thread-local key/value context attached automatically to subsequent log lines. See [MDC](https://quillcpp.readthedocs.io/en/latest/mdc.html). - **Rate-Limited Macros**: `LOG_*_LIMIT` / `LOGV_*_LIMIT` emit at most once per configured interval per call site. - **Configurable Queue Modes**: `bounded/unbounded` and `blocking/dropping` options with monitoring on dropped messages, queue reallocations, and blocked hot threads. - **Crash Handling**: Built-in signal handler for log preservation during crashes. - **Huge Pages Support (Linux)**: Leverage huge pages on the hot path for optimized performance. - **Wide Character Support (Windows)**: Logs wide strings by converting them to UTF-8 on the backend, with support for STL containers consisting of wide strings. - **Exception-Free Option**: Configurable builds with or without exception handling. - **Clean Codebase**: Maintained to high standards, warning-free even at strict levels. - **Type-Safe API**: Built on [{fmt}](https://github.com/fmtlib/fmt) library. --- ## 🚀 Performance ### System Configuration - **OS:** Linux RHEL 9.4 - **CPU:** Intel Core i5-12600 (12th Gen) @ 4.8 GHz - **Compiler:** GCC 13.1 - **Benchmark-Tuned System:** The system is specifically tuned for benchmarking. - **Command Line Parameters:** ```shell $ cat /proc/cmdline 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 ``` You can find the benchmark code on the [logger_benchmarks](https://github.com/odygrd/logger_benchmarks) repository. ### Latency The results presented in the tables below are measured in `nanoseconds (ns)`. The tables are sorted by the 95th percentile (lower is better). #### Logging Numbers `LOG_INFO(logger, "Logging int: {}, int: {}, double: {}", i, j, d)`. ##### 1 Thread Logging | Library | 50th | 75th | 90th | 95th | 99th | 99.9th | |--------------------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:| | [XTR](https://github.com/choll/xtr) | 7 | 7 | 8 | 8 | 9 | 47 | | [PlatformLab NanoLog](https://github.com/PlatformLab/NanoLog) | 8 | 8 | 8 | 8 | 9 | 203 | | [Quill Bounded Dropping Queue](https://github.com/odygrd/quill) | 8 | 8 | 9 | 9 | 10 | 12 | | [Quill Unbounded Queue](https://github.com/odygrd/quill) | 8 | 8 | 9 | 9 | 10 | 12 | | [fmtlog](https://github.com/MengRao/fmtlog) | 8 | 9 | 9 | 10 | 10 | 12 | | [MS BinLog](https://github.com/Morgan-Stanley/binlog) | 23 | 23 | 23 | 24 | 77 | 124 | | [Quill Unbounded Queue (Log Functions)](https://github.com/odygrd/quill) | 29 | 30 | 31 | 32 | 33 | 35 | | [Reckless](https://github.com/mattiasflodin/reckless) | 26 | 28 | 31 | 32 | 35 | 43 | | [Iyengar NanoLog](https://github.com/Iyengar111/NanoLog) | 94 | 102 | 145 | 173 | 1149 | 2054 | | [spdlog](https://github.com/gabime/spdlog) | 242 | 249 | 257 | 262 | 274 | 294 | | [Boost.Log](https://www.boost.org) | 3057 | 3111 | 3221 | 3261 | 3409 | 3612 | | [BqLog](https://github.com/Tencent/BqLog) | 4340 | 4564 | 4588 | 4618 | 8089 | 10536 | | [g3log](https://github.com/KjellKod/g3log) | 5017 | 5055 | 5239 | 5289 | 5503 | 5876 | ![Logging numbers 1-thread latency chart](docs/charts/numbers_1_thread_logging.svg) ##### 4 Threads Logging Simultaneously | Library | 50th | 75th | 90th | 95th | 99th | 99.9th | |--------------------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:| | [Quill Bounded Dropping Queue](https://github.com/odygrd/quill) | 13 | 13 | 14 | 14 | 17 | 23 | | [Quill Unbounded Queue](https://github.com/odygrd/quill) | 11 | 11 | 13 | 14 | 15 | 21 | | [fmtlog](https://github.com/MengRao/fmtlog) | 14 | 14 | 15 | 15 | 16 | 19 | | [XTR](https://github.com/choll/xtr) | 12 | 13 | 14 | 15 | 18 | 192 | | [PlatformLab NanoLog](https://github.com/PlatformLab/NanoLog) | 15 | 15 | 16 | 16 | 20 | 24 | | [MS BinLog](https://github.com/Morgan-Stanley/binlog) | 32 | 33 | 34 | 36 | 253 | 447 | | [Quill Unbounded Queue (Log Functions)](https://github.com/odygrd/quill) | 36 | 40 | 45 | 47 | 52 | 61 | | [Reckless](https://github.com/mattiasflodin/reckless) | 29 | 35 | 45 | 52 | 66 | 91 | | [Iyengar NanoLog](https://github.com/Iyengar111/NanoLog) | 75 | 81 | 285 | 298 | 473 | 1721 | | [spdlog](https://github.com/gabime/spdlog) | 528 | 555 | 585 | 607 | 669 | 973 | | [Boost.Log](https://www.boost.org) | 1600 | 2705 | 3126 | 3159 | 3816 | 4958 | | [BqLog](https://github.com/Tencent/BqLog) | 249 | 276 | 4595 | 5152 | 5505 | 8711 | | [g3log](https://github.com/KjellKod/g3log) | 1192 | 4236 | 5165 | 5214 | 6443 | 7844 | ![Logging numbers 4-thread latency chart](docs/charts/numbers_4_thread_logging.svg) #### Logging Large Strings Logging `std::string` over 35 characters to prevent the short string optimization. `LOG_INFO(logger, "Logging int: {}, int: {}, string: {}", i, j, large_string)`. ##### 1 Thread Logging | Library | 50th | 75th | 90th | 95th | 99th | 99.9th | |--------------------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:| | [XTR](https://github.com/choll/xtr) | 8 | 8 | 8 | 9 | 10 | 46 | | [PlatformLab NanoLog](https://github.com/PlatformLab/NanoLog) | 11 | 11 | 12 | 12 | 13 | 210 | | [Quill Bounded Dropping Queue](https://github.com/odygrd/quill) | 11 | 12 | 13 | 14 | 17 | 19 | | [fmtlog](https://github.com/MengRao/fmtlog) | 11 | 12 | 13 | 14 | 16 | 18 | | [Quill Unbounded Queue](https://github.com/odygrd/quill) | 11 | 13 | 14 | 15 | 17 | 20 | | [MS BinLog](https://github.com/Morgan-Stanley/binlog) | 24 | 25 | 25 | 26 | 78 | 125 | | [Quill Unbounded Queue (Log Functions)](https://github.com/odygrd/quill) | 33 | 34 | 36 | 37 | 40 | 42 | | [Reckless](https://github.com/mattiasflodin/reckless) | 91 | 104 | 112 | 116 | 122 | 130 | | [Iyengar NanoLog](https://github.com/Iyengar111/NanoLog) | 96 | 104 | 148 | 156 | 1034 | 1883 | | [spdlog](https://github.com/gabime/spdlog) | 216 | 223 | 230 | 236 | 247 | 259 | | [Boost.Log](https://www.boost.org) | 2871 | 3020 | 3045 | 3078 | 3169 | 3329 | | [BqLog](https://github.com/Tencent/BqLog) | 3549 | 4482 | 4517 | 4576 | 5837 | 7392 | | [g3log](https://github.com/KjellKod/g3log) | 4785 | 4822 | 5049 | 5099 | 5319 | 5688 | ![Logging large strings 1-thread latency chart](docs/charts/large_strings_1_thread_logging.svg) ##### 4 Threads Logging Simultaneously | Library | 50th | 75th | 90th | 95th | 99th | 99.9th | |--------------------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:| | [Quill Bounded Dropping Queue](https://github.com/odygrd/quill) | 9 | 11 | 14 | 16 | 21 | 28 | | [Quill Unbounded Queue](https://github.com/odygrd/quill) | 8 | 10 | 13 | 16 | 21 | 27 | | [fmtlog](https://github.com/MengRao/fmtlog) | 10 | 13 | 15 | 16 | 19 | 24 | | [XTR](https://github.com/choll/xtr) | 10 | 11 | 14 | 17 | 23 | 186 | | [PlatformLab NanoLog](https://github.com/PlatformLab/NanoLog) | 16 | 21 | 22 | 23 | 29 | 34 | | [MS BinLog](https://github.com/Morgan-Stanley/binlog) | 32 | 33 | 35 | 38 | 255 | 449 | | [Quill Unbounded Queue (Log Functions)](https://github.com/odygrd/quill) | 35 | 39 | 45 | 49 | 56 | 68 | | [Reckless](https://github.com/mattiasflodin/reckless) | 43 | 81 | 129 | 141 | 162 | 179 | | [Iyengar NanoLog](https://github.com/Iyengar111/NanoLog) | 74 | 82 | 285 | 299 | 478 | 1693 | | [spdlog](https://github.com/gabime/spdlog) | 515 | 543 | 570 | 591 | 646 | 939 | | [Boost.Log](https://www.boost.org) | 1363 | 2518 | 2931 | 2977 | 3686 | 4756 | | [g3log](https://github.com/KjellKod/g3log) | 837 | 3885 | 4900 | 4947 | 6040 | 7397 | | [BqLog](https://github.com/Tencent/BqLog) | 248 | 275 | 4634 | 5055 | 5538 | 8843 | ![Logging large strings 4-thread latency chart](docs/charts/large_strings_4_thread_logging.svg) #### Logging Complex Types Logging `std::vector` containing 16 large strings, each ranging from 50 to 60 characters. Note: some of the previous loggers do not support passing a `std::vector` as an argument. `LOG_INFO(logger, "Logging int: {}, int: {}, vector: {}", i, j, v)`. ##### 1 Thread Logging | Library | 50th | 75th | 90th | 95th | 99th | 99.9th | |-----------------------------------------------------------------|:-----:|:-----:|:-----:|:-----:|:-----:|:------:| | [Quill Bounded Dropping Queue](https://github.com/odygrd/quill) | 56 | 58 | 61 | 63 | 68 | 94 | | [MS BinLog](https://github.com/Morgan-Stanley/binlog) | 73 | 76 | 78 | 79 | 87 | 354 | | [Quill Unbounded Queue](https://github.com/odygrd/quill) | 137 | 150 | 164 | 171 | 181 | 189 | | [XTR](https://github.com/choll/xtr) | 309 | 314 | 319 | 322 | 349 | 666 | | [fmtlog](https://github.com/MengRao/fmtlog) | 750 | 788 | 823 | 847 | 896 | 982 | | [spdlog](https://github.com/gabime/spdlog) | 6749 | 6833 | 6911 | 6967 | 7217 | 7863 | | [Boost.Log](https://www.boost.org) | 90879 | 91012 | 91164 | 91251 | 92676 | 93069 | ![Logging complex types 1-thread latency chart](docs/charts/vector_1_thread_logging.svg) ##### 4 Threads Logging Simultaneously | Library | 50th | 75th | 90th | 95th | 99th | 99.9th | |-----------------------------------------------------------------|:-----:|:-----:|:-----:|:------:|:------:|:------:| | [Quill Bounded Dropping Queue](https://github.com/odygrd/quill) | 82 | 89 | 99 | 106 | 115 | 123 | | [Quill Unbounded Queue](https://github.com/odygrd/quill) | 101 | 110 | 120 | 128 | 142 | 158 | | [MS BinLog](https://github.com/Morgan-Stanley/binlog) | 103 | 113 | 122 | 130 | 299 | 518 | | [fmtlog](https://github.com/MengRao/fmtlog) | 657 | 683 | 707 | 722 | 750 | 782 | | [XTR](https://github.com/choll/xtr) | 697 | 766 | 805 | 825 | 870 | 1027 | | [spdlog](https://github.com/gabime/spdlog) | 6822 | 7021 | 7230 | 7513 | 8048 | 8903 | | [Boost.Log](https://www.boost.org) | 36382 | 69081 | 91568 | 132626 | 173810 | 203865 | ![Logging complex types 4-thread latency chart](docs/charts/vector_4_thread_logging.svg) The benchmark methodology involves logging 20 messages in a loop, calculating and storing the average latency for those 20 messages, then waiting around ~2 milliseconds, and repeating this process for a specified number of iterations. _In the `Quill Bounded Dropping` benchmarks, the dropping queue size is set to `262,144` bytes, which is double the default size of `131,072` bytes._ ### Throughput Throughput is measured by calculating the maximum number of log messages the backend logging thread can write to a log file per second (higher is better). The tests were run on the same system used for the latency benchmarks. Although Quill’s primary focus is not on maximizing throughput, it efficiently manages log messages across multiple threads. Benchmarking throughput of asynchronous logging libraries presents certain challenges. Some libraries may drop log messages, leading to smaller-than-expected log files, while others only provide asynchronous flushing, making it difficult to verify when the backend thread has fully processed all messages. For comparison, we benchmark against other asynchronous logging libraries that offer guaranteed logging with a flush-and-wait mechanism. Note that `MS BinLog` writes log data to a binary file, which requires offline formatting with an additional program—this makes it an unfair comparison, but it is included for reference. Similarly, `BqLog (binary log)` uses the compressed binary log appender, and its log files are not human-readable unless processed offline. However, it is included for reference. The other version of `BqLog` is using a text appender and produces human-readable log files. In the same way, `Platformlab Nanolog` also outputs binary logs and is expected to deliver high throughput. However, for reasons unexplained, the benchmark runs significantly slower (10x longer) than the other libraries, so it is excluded from the table. `XTR` uses ``FMT_COMPILE`` for message formatting in this benchmark. Quill does not currently use that optimisation: decoded arguments are formatted through the runtime ``fmt`` APIs, and the final log line then passes through Quill's runtime-configurable ``PatternFormatter``. Logging 4 million times the message `"Iteration: {} int: {} double: {}"` | Library | million msg/second | elapsed time | |--------------------------------------------------------------------|:------------------:|:------------:| | [MS BinLog (binary log)](https://github.com/Morgan-Stanley/binlog) | 57.72 | 69 ms | | [BqLog (binary log)](https://github.com/Tencent/BqLog) | 13.85 | 288 ms | | [XTR](https://github.com/choll/xtr) | 7.54 | 530 ms | | [BqLog](https://github.com/Tencent/BqLog) | 5.40 | 740 ms | | [Quill](https://github.com/odygrd/quill) | 4.62 | 866 ms | | [spdlog](https://github.com/gabime/spdlog) | 3.46 | 1156 ms | | [fmtlog](https://github.com/MengRao/fmtlog) | 2.65 | 1508 ms | | [Reckless](https://github.com/mattiasflodin/reckless) | 2.57 | 1555 ms | | [Quill - Macro Free Mode](https://github.com/odygrd/quill) | 2.23 | 1789 ms | | [Boost.Log](https://www.boost.org) | 0.33 | 12152 ms | ![Throughput comparison chart](docs/charts/throughput.svg) ### Compilation Time Compile times are measured on the system above using clean `Release` builds of [ `BENCHMARK_quill_compile_time`](https://github.com/odygrd/quill/blob/master/benchmarks/compile_time/compile_time_bench.cpp), which compiles `2000` auto-generated log statements with varied argument types. The measurements below were taken with `-march=x86-64-v3` for `Release`, running one clean build at a time with `-j4`. Clang builds additionally enable `-ftime-trace`. Quill intentionally keeps call-site metadata such as file, line, format string, and tags out of the frontend template identity. In the common macro-based path, that information is stored in a `MacroMetadata` object and passed as a regular function argument. As a result, multiple log statements with the same argument type pack can reuse the same `log_statement` instantiation; changing only the call-site metadata does not create a new frontend template instantiation. | Compiler | Clean Build Time | Benchmark Binary | Main TU Object | |:---------------|-----------------:|-----------------:|---------------:| | `clang 17.0.6` | `30.64 s` | `5.87 MB` | `10.10 MB` | | `gcc 13.3.1` | `61.20 s` | `6.22 MB` | `9.28 MB` | **Header include profile** — shows the additional headers pulled in when logging, following the [recommended_usage](https://github.com/odygrd/quill/blob/master/examples/recommended_usage/recommended_usage.cpp) example: > [**Open in Speedscope ** ↗](https://www.speedscope.app/#profileURL=https://raw.githubusercontent.com/odygrd/quill/master/docs/traces/recommended_usage.cpp.json) **Compile-time benchmark** — measures compilation of [2000 auto-generated log statements](https://github.com/odygrd/quill/blob/master/benchmarks/compile_time/compile_time_bench.cpp) with various arguments: > [**Open in Speedscope ** ↗](https://www.speedscope.app/#profileURL=https://raw.githubusercontent.com/odygrd/quill/master/docs/traces/compile_time_bench.cpp.json) To generate these profiles yourself: ```bash cmake -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release \ -DQUILL_BUILD_BENCHMARKS=ON -DQUILL_ENABLE_TIME_TRACE=ON \ -DCMAKE_CXX_FLAGS='-march=x86-64-v3' .. cmake --build . --target BENCHMARK_quill_compile_time -j 4 # Load the resulting .cpp.json files into https://www.speedscope.app ``` ### Verdict Quill excels in hot path latency benchmarks and supports high throughput, offering a rich set of features that outshines other logging libraries. The human-readable log files facilitate easier debugging and analysis. While initially larger, they compress efficiently, with the size difference between human-readable and binary logs becoming minimal once zipped. For example, for the same amount of messages: ``` ms_binlog_backend_total_time.blog (binary log): 177 MB ms_binlog_backend_total_time.zip (zipped binary log): 35 MB ``` ``` quill_backend_total_time.log (human-readable log): 448 MB quill_backend_total_time.zip (zipped human-readable log): 47 MB ``` If you prefer a binary-log workflow, MS BinLog is a strong alternative. It delivers excellent hot-path latency and smaller raw files, but it trades away immediate readability and requires offline processing tools. --- ## 🧩 Usage Also, see the [Quick Start Guide](https://quillcpp.readthedocs.io/en/latest/quick_start.html) for a brief introduction. ```c++ #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/Logger.h" #include "quill/sinks/ConsoleSink.h" #include "quill/std/Array.h" #include #include int main() { // Backend quill::BackendOptions backend_options; quill::Backend::start(backend_options); // Frontend auto console_sink = quill::Frontend::create_or_get_sink("sink_id_1"); quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(console_sink)); // Change the LogLevel to print everything logger->set_log_level(quill::LogLevel::TraceL3); // A log message with number 123 int a = 123; std::string l = "log"; LOG_INFO(logger, "A {} message with number {}", l, a); // libfmt formatting language is supported 3.14e+00 double pi = 3.141592653589793; LOG_INFO(logger, "libfmt formatting language is supported {:.2e}", pi); // Logging STD types is supported [1, 2, 3] std::array arr = {1, 2, 3}; LOG_INFO(logger, "Logging STD types is supported {}", arr); // Logging STD types is supported [arr: [1, 2, 3]] LOGV_INFO(logger, "Logging STD types is supported", arr); // A message with two variables [a: 123, b: 3.17] double b = 3.17; LOGV_INFO(logger, "A message with two variables", a, b); for (uint32_t i = 0; i < 10; ++i) { // Will only log the message once per second LOG_INFO_LIMIT(std::chrono::seconds{1}, logger, "A {} message with number {}", l, a); LOGV_INFO_LIMIT(std::chrono::seconds{1}, logger, "A message with two variables", a, b); } LOG_TRACE_L3(logger, "Support for floats {:03.2f}", 1.23456); LOG_TRACE_L2(logger, "Positional arguments are {1} {0} ", "too", "supported"); LOG_TRACE_L1(logger, "{:>30}", std::string_view {"right aligned"}); LOG_DEBUG(logger, "Debugging foo {}", 1234); LOG_INFO(logger, "Welcome to Quill!"); LOG_WARNING(logger, "A warning message."); LOG_ERROR(logger, "An error message. error code {}", 123); LOG_CRITICAL(logger, "A critical error."); } ``` ### Output ![example output](docs/example_output.svg) ### External CMake #### Building and Installing Quill To get started with Quill, clone the repository and install it using CMake: ```bash git clone https://github.com/odygrd/quill.git cd quill mkdir cmake_build cd cmake_build cmake .. make install ``` - **Custom Installation**: Specify a custom directory with `-DCMAKE_INSTALL_PREFIX=/path/to/install/dir`. - **Build Examples**: Include examples with `-DQUILL_BUILD_EXAMPLES=ON`. Next, add Quill to your project using `find_package()`: ```cmake find_package(quill REQUIRED) target_link_libraries(your_target PUBLIC quill::quill) ``` #### Sample Directory Structure Organize your project directory like this: ``` my_project/ ├── CMakeLists.txt ├── main.cpp ``` #### Sample CMakeLists.txt Here is a minimal `CMakeLists.txt`: ```cmake # If Quill is in a non-standard directory, specify its path. set(CMAKE_PREFIX_PATH /path/to/quill) # Find and link the Quill library. find_package(quill REQUIRED) add_executable(example main.cpp) target_link_libraries(example PUBLIC quill::quill) ``` ### Embedded CMake If you prefer to vendor Quill directly, add it as a subdirectory: #### Sample Directory Structure ``` my_project/ ├── quill/ # Quill repo folder ├── CMakeLists.txt ├── main.cpp ``` #### Sample CMakeLists.txt Use this `CMakeLists.txt` to include Quill directly: ```cmake cmake_minimum_required(VERSION 3.8) project(my_project) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(quill) add_executable(my_project main.cpp) target_link_libraries(my_project PUBLIC quill::quill) ``` ### Android NDK Android usually works without special handling. If your toolchain does not support thread names, configure with: ```bash -DQUILL_NO_THREAD_NAME_SUPPORT:BOOL=ON ``` For timestamps, use `quill::ClockSourceType::System`. Quill also includes an `AndroidSink` for Android's logging system. #### Minimal Example to Start Logging on Android ```c++ quill::Backend::start(); auto sink = quill::Frontend::create_or_get_sink("app", [](){ quill::AndroidSinkConfig asc; asc.set_tag("app"); asc.set_format_message(true); return asc; }()); auto logger = quill::Frontend::create_or_get_logger("root", std::move(sink), quill::PatternFormatterOptions {}, quill::ClockSourceType::System); LOG_INFO(logger, "Test {}", 123); ``` ### Meson #### Using WrapDB Install Quill from Meson's `wrapdb` with: ```bash meson wrap install quill ``` #### Manual Integration Or copy the repository into `subprojects` and add the following to `meson.build`: ```meson quill = subproject('quill') quill_dep = quill.get_variable('quill_dep') my_build_target = executable('name', 'main.cpp', dependencies : [quill_dep], install : true) ``` ### Bazel #### Using Bzlmod Quill is available on `Bzlmod`. #### Manual Integration For manual setup, add Quill to your `BUILD.bazel` file like this: ```bazel cc_binary(name = "app", srcs = ["main.cpp"], deps = ["//quill_path:quill"]) ``` --- ## 📠Design Quill is split into a **hot frontend** and a **cold backend**. - Each frontend thread owns a lock-free SPSC queue. `LOG_*` macros binary-serialize arguments directly into that queue — no shared state, no contention between threads, no formatting work on the caller. - A single backend worker drains all queues, merges events in timestamp order, invokes the per-argument-pack decode function to reconstruct arguments, runs `{fmt}` formatting and the `PatternFormatter`, and writes the resulting log lines or metric samples to the attached `Sink`s. ### Frontend (caller-thread) When invoking a `LOG_` macro: 1. Creates a static constexpr metadata object containing the format string and source location. 2. Pushes the event into the SPSC lock-free queue. For each log message, Quill enqueues: | Variable | Description | |------------|:--------------------------------------------------------------------------------------------------------------:| | timestamp | Current timestamp | | Metadata* | Pointer to metadata information | | Logger* | Pointer to the logger instance | | DecodeFunc | A pointer to a templated function containing all the log message argument types, used for decoding the message | | Args... | A serialized binary copy of each log message argument that was passed to the `LOG_` macro | When invoking `METRIC(...)` or `logger->publish_metric()`: 1. Reuses pre-registered `MetricMetadata`, so metric names and labels are not serialized again on the hot path. 2. Pushes a compact fixed-size sample record to the same SPSC queue. | Variable | Description | |-----------------|:---------------------------------------------------------------------:| | timestamp | Current timestamp | | MetricMetadata* | Pointer to the pre-registered metric name and labels | | Logger* | Pointer to the logger instance | | value | The actual sample value as a `double` (counter delta, latency, gauge) | ### Backend The backend thread drains the SPSC queue, reconstructs log events, forwards metric samples to `Sink::write_metric()`, and fans each log or metric event out to the sinks attached to the logger. ### Architecture Overview The diagram below shows the end-to-end flow from hot frontend threads to the backend worker and sinks. ![design diagram](docs/design.drawio.svg) --- ## 🚨 Caveats **Do not log from destructors of static or global objects.** Quill's internal singletons are function-local statics destroyed in reverse construction order. If a static object's constructor triggers the first log call, the library singletons are constructed *after* that object and destroyed *before* it. Logging from that destructor will then touch already-destroyed state. **Use `fork()` with care.** Quill starts a background thread, and `fork()` interacts poorly with multithreaded processes. If you need logging in child processes, call `quill::Backend::start()` after `fork()` in each process that should log, and write parent and child output to different files. Example: ```c++ #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/Logger.h" #include "quill/sinks/FileSink.h" int main() { // DO NOT CALL THIS BEFORE FORK // quill::Backend::start(); if (fork() == 0) { quill::Backend::start(); // Write child output to its own file. auto file_sink = quill::Frontend::create_or_get_sink("child.log"); quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(file_sink)); LOG_INFO(logger, "Hello from Child {}", 123); } else { quill::Backend::start(); // Write parent output to its own file. auto file_sink = quill::Frontend::create_or_get_sink("parent.log"); quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(file_sink)); LOG_INFO(logger, "Hello from Parent {}", 123); } } ``` --- ## 📠License Quill is licensed under the [MIT License](https://opensource.org/licenses/MIT). Quill depends on third party libraries with separate copyright notices and license terms. Your use of the source code for these subcomponents is subject to the terms and conditions of the following licenses. - ([MIT License](https://opensource.org/licenses/MIT)) [{fmt}](https://github.com/fmtlib/fmt/blob/master/LICENSE) - ([MIT License](https://opensource.org/licenses/MIT)) [doctest](https://github.com/onqtam/doctest/blob/master/LICENSE.txt) quill-12.1.0/benchmarks/000077500000000000000000000000001522564103500150415ustar00rootroot00000000000000quill-12.1.0/benchmarks/CMakeLists.txt000066400000000000000000000001461522564103500176020ustar00rootroot00000000000000add_subdirectory(hot_path_latency) add_subdirectory(backend_throughput) add_subdirectory(compile_time)quill-12.1.0/benchmarks/backend_throughput/000077500000000000000000000000001522564103500207215ustar00rootroot00000000000000quill-12.1.0/benchmarks/backend_throughput/CMakeLists.txt000066400000000000000000000007221522564103500234620ustar00rootroot00000000000000add_executable(BENCHMARK_quill_backend_throughput quill_backend_throughput.cpp) set_common_compile_options(BENCHMARK_quill_backend_throughput) target_link_libraries(BENCHMARK_quill_backend_throughput quill) add_executable(BENCHMARK_quill_backend_throughput_no_buffering quill_backend_throughput_no_buffering.cpp) set_common_compile_options(BENCHMARK_quill_backend_throughput_no_buffering) target_link_libraries(BENCHMARK_quill_backend_throughput_no_buffering quill)quill-12.1.0/benchmarks/backend_throughput/quill_backend_throughput.cpp000066400000000000000000000052331522564103500265160ustar00rootroot00000000000000#include #include #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/sinks/FileSink.h" static constexpr size_t total_iterations = 4'000'000; /** * The backend worker just spins, so we just measure the total time elapsed for total_iterations */ int main() { // main thread affinity - pinning can legitimately fail (e.g. Apple Silicon does not support // the affinity policy); warn and continue instead of terminating the benchmark #if defined(QUILL_NO_EXCEPTIONS) quill::detail::set_cpu_affinity({1}); #else try { quill::detail::set_cpu_affinity({1}); } catch (std::exception const& e) { std::cerr << "Failed to set cpu affinity: " << e.what() << std::endl; } #endif quill::BackendOptions backend_options; backend_options.cpu_affinity = {5}; backend_options.sleep_duration = std::chrono::nanoseconds{0}; backend_options.log_timestamp_ordering_grace_period = std::chrono::microseconds{1}; // Start the logging backend thread and give it some tiem to init quill::Backend::start(backend_options); // Create a file sink to write to a file std::shared_ptr file_sink = quill::Frontend::create_or_get_sink( "quill_backend_total_time.log", []() { quill::FileSinkConfig cfg; cfg.set_open_mode('w'); return cfg; }(), quill::FileEventNotifier{}); quill::Logger* logger = quill::Frontend::create_or_get_logger( "bench_logger", std::move(file_sink), quill::PatternFormatterOptions{ "%(time) [%(thread_id)] %(short_source_location) %(log_level) %(message)", "%H:%M:%S.%Qns", quill::Timezone::LocalTime, false}); LOG_INFO(logger, "preallocate"); logger->flush_log(0); // start counting the time until backend worker finishes auto const start_time = std::chrono::steady_clock::now(); for (size_t iteration = 0; iteration < total_iterations; ++iteration) { LOG_INFO(logger, "Iteration: {} int: {} double: {}", iteration, iteration * 2, static_cast(iteration) / 2); } // block until all messages are flushed logger->flush_log(0); auto const end_time = std::chrono::steady_clock::now(); auto const delta = end_time - start_time; auto delta_d = std::chrono::duration_cast>(delta).count(); std::cout << fmtquill::format( "Throughput is {:.2f} million msgs/sec average, total time elapsed: {} ms for {} " "log messages \n", total_iterations / delta_d / 1e6, std::chrono::duration_cast(delta).count(), total_iterations) << std::endl; } quill-12.1.0/benchmarks/backend_throughput/quill_backend_throughput_no_buffering.cpp000066400000000000000000000054501522564103500312420ustar00rootroot00000000000000#include #include #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/sinks/FileSink.h" static constexpr size_t total_iterations = 4'000'000; /** * The backend worker just spins, so we just measure the total time elapsed for total_iterations */ int main() { // main thread affinity - pinning can legitimately fail (e.g. Apple Silicon does not support // the affinity policy); warn and continue instead of terminating the benchmark #if defined(QUILL_NO_EXCEPTIONS) quill::detail::set_cpu_affinity({0}); #else try { quill::detail::set_cpu_affinity({0}); } catch (std::exception const& e) { std::cerr << "Failed to set cpu affinity: " << e.what() << std::endl; } #endif quill::BackendOptions backend_options; backend_options.cpu_affinity = {5}; backend_options.sleep_duration = std::chrono::nanoseconds{0}; backend_options.transit_events_hard_limit = 1; backend_options.transit_events_soft_limit = 1; backend_options.log_timestamp_ordering_grace_period = std::chrono::microseconds{1}; // Start the logging backend thread and give it some tiem to init quill::Backend::start(backend_options); std::this_thread::sleep_for(std::chrono::milliseconds{100}); // Create a file sink to write to a file std::shared_ptr file_sink = quill::Frontend::create_or_get_sink( "quill_backend_total_time.log", []() { quill::FileSinkConfig cfg; cfg.set_open_mode('w'); return cfg; }(), quill::FileEventNotifier{}); quill::Logger* logger = quill::Frontend::create_or_get_logger( "bench_logger", std::move(file_sink), quill::PatternFormatterOptions{ "%(time) [%(thread_id)] %(short_source_location) %(log_level) %(message)", "%H:%M:%S.%Qns", quill::Timezone::LocalTime, false}); ; quill::Frontend::preallocate(); // start counting the time until backend worker finishes auto const start_time = std::chrono::steady_clock::now(); for (size_t iteration = 0; iteration < total_iterations; ++iteration) { LOG_INFO(logger, "Iteration: {} int: {} double: {}", iteration, iteration * 2, static_cast(iteration) / 2); } // block until all messages are flushed logger->flush_log(0); auto const end_time = std::chrono::steady_clock::now(); auto const delta = end_time - start_time; auto delta_d = std::chrono::duration_cast>(delta).count(); std::cout << fmtquill::format( "Throughput is {:.2f} million msgs/sec average, total time elapsed: {} ms for {} " "log messages \n", total_iterations / delta_d / 1e6, std::chrono::duration_cast(delta).count(), total_iterations) << std::endl; } quill-12.1.0/benchmarks/compile_time/000077500000000000000000000000001522564103500175075ustar00rootroot00000000000000quill-12.1.0/benchmarks/compile_time/CMakeLists.txt000066400000000000000000000003511522564103500222460ustar00rootroot00000000000000add_subdirectory(qwrapper) add_executable(BENCHMARK_quill_compile_time compile_time_bench.cpp) set_common_compile_options(BENCHMARK_quill_compile_time) target_link_libraries(BENCHMARK_quill_compile_time qwrapper_compile_time_bench) quill-12.1.0/benchmarks/compile_time/compile_time_bench.cpp000066400000000000000000010241151522564103500240240ustar00rootroot00000000000000#include "qwrapper/qwrapper.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/Logger.h" int main() { setup_quill("recommended_usage.log"); auto logger = quill::Frontend::get_logger("root"); LOG_INFO(logger, "example lazy brown {} {} {}", "example2", 4.0f, "example3"); LOG_INFO(logger, "jumps brown example lazy {} {} {} {} {}", std::string("str1"), static_cast(9), 6LL, "example1", static_cast(10)); LOG_INFO(logger, "brown test jumps fox {} {} {} {} {} {} {} {} {}", false, std::string("str1"), 3.0, "example3", 6LL, "example2", static_cast(10), 1, true); LOG_INFO(logger, "dog test example lazy {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 7UL, static_cast(9), false, 6LL, 5L, true, "example3", "example2", std::string("str1")); LOG_INFO(logger, "example fox lazy {} {} {} {} {} {} {} {} {} {}", "example1", 4.0f, 7UL, 5L, true, 2, 3.0, 6LL, false, "example3"); LOG_INFO(logger, "quick test over fox {} {} {} {}", true, static_cast(9), "example3", 6LL); LOG_INFO(logger, "lazy logging test {} {} {} {} {}", 8ULL, 4.0f, std::string_view("view2"), "example1", "example3"); LOG_INFO(logger, "lazy over fox {} {}", std::string_view("view1"), 8ULL); LOG_INFO(logger, "lazy fox brown {} {} {}", 5L, static_cast(9), static_cast(10)); LOG_INFO(logger, "logging brown over dog {} {} {} {} {} {} {} {}", std::string_view("view1"), "example2", std::string("str2"), std::string("str1"), 8ULL, std::string_view("view2"), false, 2); LOG_INFO(logger, "brown fox test example {} {} {} {}", static_cast(10), 6LL, static_cast(9), 7UL); LOG_INFO(logger, "fox logging brown {} {} {} {} {} {} {} {}", 2, std::string("str2"), static_cast(9), "example2", false, 7UL, "example3", 4.0f); LOG_INFO(logger, "over quick logging lazy {} {} {} {}", std::string("str2"), "example3", 7UL, 5L); LOG_INFO(logger, "dog over test jumps {} {} {} {} {}", 1, std::string_view("view2"), 8ULL, "example3", 4.0f); LOG_INFO(logger, "fox example dog {}", 5L); LOG_INFO(logger, "example test fox dog {} {} {} {} {} {} {} {}", static_cast(10), 6LL, 3.0, static_cast(9), 2, false, std::string_view("view2"), std::string_view("view1")); LOG_INFO(logger, "test lazy jumps fox {} {} {} {} {} {}", 4.0f, std::string_view("view1"), static_cast(10), std::string("str2"), 3.0, true); LOG_INFO(logger, "over jumps brown {}", 4.0f); LOG_INFO(logger, "dog brown over {} {} {} {} {} {} {} {}", "example1", static_cast(10), false, 1, 6LL, std::string_view("view1"), 2, 8ULL); LOG_INFO(logger, "over test jumps {} {} {} {} {} {} {} {}", true, std::string("str1"), 6LL, "example3", 1, 7UL, 2, "example1"); LOG_INFO(logger, "over dog example fox {} {} {} {} {} {} {} {} {} {}", 8ULL, 2, 5L, std::string("str1"), std::string_view("view1"), std::string_view("view2"), 1, "example1", 7UL, std::string("str2")); LOG_INFO(logger, "logging lazy fox {} {} {} {} {} {} {} {} {} {}", 8ULL, std::string("str2"), 7UL, false, std::string("str1"), "example3", 3.0, std::string_view("view1"), "example1", 6LL); LOG_INFO(logger, "logging example quick dog {} {} {} {} {} {} {} {} {}", 6LL, 1, 5L, 3.0, "example3", 4.0f, 8ULL, std::string("str1"), false); LOG_INFO(logger, "example jumps over {} {} {} {} {} {}", 6LL, static_cast(9), static_cast(10), "example3", true, 7UL); LOG_INFO(logger, "dog fox brown quick {} {} {}", 1, 5L, 6LL); LOG_INFO(logger, "brown example dog {} {} {} {}", std::string("str2"), 6LL, true, std::string_view("view1")); LOG_INFO(logger, "jumps example fox test {} {}", 6LL, std::string("str1")); LOG_INFO(logger, "brown over dog fox {} {} {} {} {} {} {}", std::string("str1"), std::string("str2"), 4.0f, false, 8ULL, "example2", true); LOG_INFO(logger, "example over fox dog {} {} {} {} {} {} {} {} {} {}", "example1", 1, static_cast(9), static_cast(10), "example2", std::string("str1"), false, std::string_view("view1"), 4.0f, 7UL); LOG_INFO(logger, "brown example test quick {} {} {} {} {} {}", std::string("str2"), 3.0, static_cast(9), "example2", std::string("str1"), 8ULL); LOG_INFO(logger, "fox brown jumps {} {} {} {} {} {} {} {} {} {}", "example3", std::string("str2"), "example2", 7UL, false, 6LL, 5L, 4.0f, 2, std::string("str1")); LOG_INFO(logger, "brown quick dog over {} {} {} {} {} {} {} {}", 1, 4.0f, std::string_view("view1"), false, true, "example2", static_cast(10), std::string("str2")); LOG_INFO(logger, "lazy jumps brown {} {} {}", 8ULL, 5L, "example1"); LOG_INFO(logger, "example dog over {} {} {} {} {} {}", static_cast(9), "example2", 3.0, std::string("str1"), 5L, std::string_view("view2")); LOG_INFO(logger, "fox example dog {} {} {} {} {} {}", true, "example2", 3.0, 5L, 6LL, 1); LOG_INFO(logger, "example lazy dog {} {} {} {} {} {} {}", 6LL, std::string("str2"), 4.0f, "example2", std::string("str1"), static_cast(10), 8ULL); LOG_INFO(logger, "fox logging brown {} {} {} {} {} {}", 2, true, "example1", 6LL, std::string_view("view1"), 7UL); LOG_INFO(logger, "example brown over test {} {}", 5L, std::string_view("view1")); LOG_INFO(logger, "over test dog {} {} {} {} {}", std::string("str1"), std::string_view("view1"), "example2", "example1", 6LL); LOG_INFO(logger, "logging test example {} {} {} {} {} {} {} {} {} {}", 6LL, "example3", static_cast(9), true, 7UL, 5L, std::string_view("view2"), 2, 1, std::string_view("view1")); LOG_INFO(logger, "example test lazy quick {} {} {} {} {} {} {} {}", std::string("str1"), 6LL, 7UL, std::string_view("view2"), static_cast(9), 5L, std::string("str2"), "example1"); LOG_INFO(logger, "over lazy logging {} {} {} {} {}", "example3", std::string_view("view1"), 6LL, false, "example2"); LOG_INFO(logger, "lazy example jumps over {} {} {} {} {} {} {} {}", 3.0, "example3", 2, "example2", 4.0f, 6LL, true, static_cast(10)); LOG_INFO(logger, "fox brown example {}", 5L); LOG_INFO(logger, "jumps lazy test over {} {}", false, std::string_view("view2")); LOG_INFO(logger, "lazy over quick {} {} {} {} {} {} {}", true, 7UL, std::string("str1"), "example1", 5L, 4.0f, static_cast(9)); LOG_INFO(logger, "fox brown over jumps {} {} {} {} {} {} {}", 1, 3.0, true, std::string("str2"), 4.0f, 6LL, "example3"); LOG_INFO(logger, "example logging test quick {} {} {} {} {} {} {}", 1, "example2", static_cast(9), 6LL, static_cast(10), 5L, std::string_view("view1")); LOG_INFO(logger, "brown logging quick test {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 5L, true, 8ULL, "example1", 2, 3.0, "example3", std::string("str2")); LOG_INFO(logger, "logging dog over fox {} {} {}", false, std::string_view("view2"), 7UL); LOG_INFO(logger, "quick fox test {} {} {} {} {} {} {} {}", std::string("str2"), 4.0f, 8ULL, "example3", 5L, false, 7UL, std::string_view("view1")); LOG_INFO(logger, "over logging lazy {} {} {} {} {} {} {} {}", 7UL, "example1", 3.0, "example2", std::string_view("view2"), static_cast(9), std::string_view("view1"), 1); LOG_INFO(logger, "brown dog example fox {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), 1, 4.0f, 2, "example1", "example2", 7UL, 5L); LOG_INFO(logger, "jumps brown dog test {} {} {} {} {} {} {} {} {}", "example2", std::string("str2"), 7UL, 2, static_cast(9), false, 6LL, 5L, 3.0); LOG_INFO(logger, "quick lazy logging {} {} {}", 4.0f, "example1", static_cast(10)); LOG_INFO(logger, "jumps test quick fox {} {} {} {} {} {} {} {}", false, 4.0f, 1, static_cast(9), "example1", 2, 6LL, "example3"); LOG_INFO(logger, "over example dog {} {} {} {} {}", 6LL, 5L, "example1", 1, 4.0f); LOG_INFO(logger, "brown fox logging {} {} {} {}", 5L, 3.0, 7UL, static_cast(9)); LOG_INFO(logger, "over example brown {} {} {} {} {} {} {} {} {}", 2, std::string("str1"), 7UL, true, false, 1, 5L, std::string("str2"), "example3"); LOG_INFO(logger, "lazy test over jumps {} {} {} {} {} {} {} {} {} {}", false, "example3", std::string_view("view2"), static_cast(9), 2, 4.0f, std::string("str2"), std::string_view("view1"), std::string("str1"), "example2"); LOG_INFO(logger, "test quick brown {} {}", std::string_view("view2"), std::string("str2")); LOG_INFO(logger, "dog example over lazy {} {} {}", "example3", static_cast(10), true); LOG_INFO(logger, "over test brown lazy {} {}", 3.0, 4.0f); LOG_INFO(logger, "lazy jumps example {} {} {} {} {} {} {}", std::string_view("view1"), false, 6LL, "example2", true, "example1", static_cast(9)); LOG_INFO(logger, "fox example jumps over {} {} {} {} {} {} {} {} {}", 4.0f, 7UL, "example2", 8ULL, std::string("str2"), 6LL, false, "example3", static_cast(9)); LOG_INFO(logger, "dog example lazy jumps {} {} {} {} {} {} {} {}", 3.0, std::string_view("view2"), 2, 6LL, std::string_view("view1"), std::string("str1"), 4.0f, std::string("str2")); LOG_INFO(logger, "quick lazy test dog {} {}", "example1", std::string("str1")); LOG_INFO(logger, "fox example quick dog {} {} {} {} {} {} {} {}", 2, 6LL, static_cast(10), 7UL, std::string_view("view1"), 1, "example2", false); LOG_INFO(logger, "jumps test quick fox {} {} {} {} {} {} {} {} {}", 8ULL, 2, std::string_view("view2"), false, 6LL, 3.0, static_cast(9), "example1", "example2"); LOG_INFO(logger, "dog jumps quick lazy {} {} {}", 2, 4.0f, "example2"); LOG_INFO(logger, "dog over brown logging {} {} {} {}", std::string("str1"), 1, "example2", false); LOG_INFO(logger, "dog lazy over example {} {} {} {}", 2, std::string("str2"), std::string("str1"), "example1"); LOG_INFO(logger, "logging jumps brown fox {} {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view2"), 7UL, std::string("str1"), 3.0, true, false, 6LL, 2, static_cast(10)); LOG_INFO(logger, "example over jumps brown {} {} {} {} {}", std::string_view("view2"), std::string("str2"), 3.0, 2, 4.0f); LOG_INFO(logger, "example dog jumps lazy {} {} {} {} {} {}", 8ULL, "example3", "example2", 6LL, true, false); LOG_INFO(logger, "example dog fox {} {} {} {} {} {} {} {} {}", "example2", 1, 3.0, std::string("str1"), "example1", 8ULL, std::string_view("view2"), false, 2); LOG_INFO(logger, "example fox over {} {} {} {} {} {} {}", 7UL, 6LL, static_cast(10), true, 4.0f, "example2", 5L); LOG_INFO(logger, "lazy example jumps logging {} {} {} {} {} {} {}", false, "example3", 4.0f, "example1", 8ULL, 3.0, std::string_view("view2")); LOG_INFO(logger, "test dog lazy {} {} {}", std::string_view("view2"), 3.0, 5L); LOG_INFO(logger, "jumps example over logging {} {} {}", 7UL, 4.0f, static_cast(9)); LOG_INFO(logger, "dog example jumps quick {} {} {} {}", 2, 5L, 1, static_cast(9)); LOG_INFO(logger, "test quick fox over {} {} {} {} {}", "example3", 1, 7UL, "example2", std::string_view("view1")); LOG_INFO(logger, "brown jumps over {} {} {} {} {} {} {} {} {}", "example2", false, std::string_view("view1"), std::string("str2"), true, "example3", 3.0, 5L, static_cast(9)); LOG_INFO(logger, "dog over fox {} {} {} {}", std::string("str2"), std::string("str1"), 1, "example2"); LOG_INFO(logger, "brown lazy dog over {} {} {} {} {}", std::string_view("view2"), 3.0, 4.0f, true, std::string_view("view1")); LOG_INFO(logger, "jumps lazy example {} {} {} {} {} {} {} {} {}", static_cast(9), "example3", std::string_view("view2"), std::string("str1"), true, 7UL, static_cast(10), 6LL, 5L); LOG_INFO(logger, "dog quick jumps {} {} {} {} {} {} {} {} {} {}", "example3", 5L, true, std::string("str1"), 8ULL, "example2", std::string_view("view1"), 1, 7UL, "example1"); LOG_INFO(logger, "jumps quick example {} {} {} {} {} {} {}", 7UL, 5L, 2, static_cast(9), std::string_view("view2"), 6LL, std::string("str1")); LOG_INFO(logger, "quick logging brown {} {} {} {} {} {} {}", 3.0, "example1", static_cast(10), 6LL, static_cast(9), 2, "example2"); LOG_INFO(logger, "example test dog quick {}", static_cast(9)); LOG_INFO(logger, "lazy jumps dog {}", 7UL); LOG_INFO(logger, "example fox quick {} {} {} {} {} {} {}", std::string_view("view2"), 7UL, 2, 8ULL, std::string("str1"), 6LL, 4.0f); LOG_INFO(logger, "brown over dog test {} {}", 7UL, "example3"); LOG_INFO(logger, "logging dog fox test {} {} {} {} {} {}", 4.0f, static_cast(9), true, std::string_view("view2"), static_cast(10), std::string("str1")); LOG_INFO(logger, "quick dog test {} {} {} {} {} {} {}", 6LL, 8ULL, "example2", std::string("str1"), "example1", true, false); LOG_INFO(logger, "jumps dog logging over {} {} {} {}", "example1", static_cast(10), 4.0f, false); LOG_INFO(logger, "lazy dog example {} {} {} {} {} {} {} {} {}", true, 1, 2, 5L, static_cast(10), "example1", 3.0, 8ULL, "example3"); LOG_INFO(logger, "fox dog lazy jumps {} {} {}", std::string_view("view1"), 3.0, 8ULL); LOG_INFO(logger, "lazy logging test quick {} {} {}", 5L, std::string_view("view2"), std::string("str1")); LOG_INFO(logger, "jumps logging quick {}", false); LOG_INFO(logger, "quick logging over {} {} {} {} {} {} {} {}", 5L, std::string_view("view1"), 1, std::string_view("view2"), true, "example3", static_cast(10), false); LOG_INFO(logger, "fox lazy test {} {} {} {} {} {} {}", std::string("str2"), "example3", 6LL, 1, true, false, 4.0f); LOG_INFO(logger, "fox over quick dog {} {} {} {}", "example2", true, static_cast(10), std::string("str1")); LOG_INFO(logger, "brown fox dog logging {} {} {} {} {} {} {} {}", 3.0, static_cast(10), std::string_view("view1"), 7UL, 4.0f, false, 1, "example1"); LOG_INFO(logger, "fox logging quick lazy {} {} {} {} {} {} {}", 5L, true, "example1", 6LL, std::string_view("view2"), "example2", static_cast(10)); LOG_INFO(logger, "quick dog jumps example {} {} {} {}", 6LL, std::string_view("view1"), static_cast(10), std::string("str1")); LOG_INFO(logger, "quick brown fox {} {} {} {} {} {} {} {} {} {}", std::string("str1"), 2, std::string_view("view1"), 4.0f, false, "example1", 5L, static_cast(10), static_cast(9), std::string("str2")); LOG_INFO(logger, "dog quick brown {} {} {} {} {} {} {} {}", true, static_cast(9), 8ULL, std::string("str2"), static_cast(10), 6LL, "example2", 2); LOG_INFO(logger, "jumps dog logging over {} {} {} {} {} {} {} {}", 8ULL, true, std::string("str2"), "example2", 4.0f, 5L, 6LL, static_cast(10)); LOG_INFO(logger, "dog lazy example {}", static_cast(9)); LOG_INFO(logger, "brown logging lazy {} {} {} {} {} {}", std::string_view("view2"), 5L, 2, static_cast(10), true, "example1"); LOG_INFO(logger, "jumps over brown {} {} {} {} {} {}", false, true, static_cast(9), 2, std::string("str2"), "example3"); LOG_INFO(logger, "lazy example quick {} {} {} {} {}", true, 3.0, 7UL, 4.0f, std::string_view("view1")); LOG_INFO(logger, "logging dog over {} {} {} {} {} {}", std::string_view("view1"), 7UL, "example3", true, static_cast(10), 5L); LOG_INFO(logger, "jumps quick logging {} {}", 2, 7UL); LOG_INFO(logger, "test lazy brown jumps {} {} {} {} {} {} {} {}", "example1", std::string("str1"), 4.0f, 3.0, static_cast(10), std::string_view("view1"), 6LL, 7UL); LOG_INFO(logger, "jumps example lazy test {} {}", 1, true); LOG_INFO(logger, "jumps over dog {} {} {} {} {} {} {}", "example3", std::string_view("view1"), static_cast(9), static_cast(10), std::string_view("view2"), true, 1); LOG_INFO(logger, "logging dog example {} {} {} {}", false, 5L, std::string("str2"), static_cast(10)); LOG_INFO(logger, "logging quick brown {} {} {} {} {} {} {} {} {} {}", 8ULL, "example3", std::string("str1"), "example1", "example2", 1, 3.0, 4.0f, 7UL, std::string_view("view2")); LOG_INFO(logger, "logging over test {} {} {} {} {} {} {} {} {}", 2, std::string_view("view2"), "example1", 6LL, true, 7UL, static_cast(9), static_cast(10), 3.0); LOG_INFO(logger, "over example fox dog {} {}", std::string_view("view1"), 1); LOG_INFO(logger, "quick logging lazy dog {} {}", "example2", std::string("str2")); LOG_INFO(logger, "lazy over quick example {} {} {} {} {} {} {}", std::string("str2"), false, 4.0f, std::string_view("view2"), 3.0, 6LL, std::string("str1")); LOG_INFO(logger, "test dog brown {} {} {} {} {} {} {} {} {}", std::string("str1"), "example2", 4.0f, 3.0, 8ULL, static_cast(10), false, 7UL, 5L); LOG_INFO(logger, "brown quick logging jumps {} {} {} {} {} {}", static_cast(10), "example2", true, false, 2, std::string_view("view1")); LOG_INFO(logger, "quick over example {} {} {} {} {} {} {}", 5L, 1, 4.0f, std::string_view("view2"), std::string("str2"), "example1", 3.0); LOG_INFO(logger, "fox quick over test {} {}", std::string_view("view1"), 3.0); LOG_INFO(logger, "dog lazy fox jumps {} {} {} {} {} {} {} {} {} {}", "example3", 1, 7UL, static_cast(10), std::string("str2"), "example2", "example1", static_cast(9), 6LL, 4.0f); LOG_INFO(logger, "dog fox jumps example {} {} {} {} {} {} {} {}", static_cast(9), "example3", 5L, 7UL, 2, std::string_view("view2"), false, static_cast(10)); LOG_INFO(logger, "dog quick example lazy {} {} {} {} {} {} {} {}", 8ULL, 2, "example3", 4.0f, std::string_view("view2"), static_cast(9), static_cast(10), 6LL); LOG_INFO(logger, "over example brown {}", 6LL); LOG_INFO(logger, "logging test jumps quick {} {} {} {} {}", true, std::string("str2"), 2, std::string_view("view1"), 7UL); LOG_INFO(logger, "brown fox over {} {} {} {} {} {} {} {} {} {}", static_cast(10), std::string_view("view2"), false, std::string("str1"), "example1", 7UL, std::string("str2"), true, 6LL, 1); LOG_INFO(logger, "logging test dog fox {}", 3.0); LOG_INFO(logger, "over brown dog {} {} {} {} {} {} {}", "example1", "example2", 6LL, std::string("str1"), 7UL, std::string_view("view1"), false); LOG_INFO(logger, "fox over lazy {} {} {} {} {} {} {} {} {} {}", static_cast(9), 8ULL, 5L, 6LL, std::string_view("view2"), std::string_view("view1"), 1, std::string("str1"), "example2", 3.0); LOG_INFO(logger, "lazy quick fox {} {} {} {}", std::string("str2"), "example3", 1, std::string_view("view2")); LOG_INFO(logger, "brown fox logging lazy {} {} {} {} {}", std::string_view("view2"), std::string("str1"), 5L, std::string_view("view1"), "example3"); LOG_INFO(logger, "brown over fox {} {} {}", 2, 6LL, 4.0f); LOG_INFO(logger, "logging fox jumps over {} {} {} {} {} {} {} {}", 7UL, 4.0f, "example1", 8ULL, "example2", 5L, false, std::string("str2")); LOG_INFO(logger, "over test logging jumps {} {} {} {} {} {}", true, 4.0f, "example1", 7UL, std::string_view("view1"), "example3"); LOG_INFO(logger, "example quick test {} {} {} {} {} {} {} {}", std::string("str1"), 7UL, 6LL, 3.0, 2, 8ULL, 1, static_cast(10)); LOG_INFO(logger, "example brown quick test {} {} {} {} {} {} {} {}", 2, false, 6LL, 4.0f, std::string_view("view1"), 8ULL, "example3", "example2"); LOG_INFO(logger, "brown example quick test {} {}", std::string("str1"), 8ULL); LOG_INFO(logger, "logging example brown {} {} {} {} {}", std::string("str1"), 5L, 4.0f, static_cast(9), "example1"); LOG_INFO(logger, "quick logging lazy {} {}", static_cast(9), "example3"); LOG_INFO(logger, "dog jumps over fox {} {} {} {} {} {} {}", 3.0, static_cast(9), 6LL, false, 7UL, std::string_view("view1"), true); LOG_INFO(logger, "brown dog example {} {} {} {} {} {} {} {} {}", "example1", std::string("str2"), true, static_cast(10), 7UL, 8ULL, 1, std::string("str1"), std::string_view("view1")); LOG_INFO(logger, "example test quick logging {} {} {} {} {} {} {} {} {}", 6LL, "example1", "example3", 1, false, static_cast(10), 2, std::string("str2"), std::string("str1")); LOG_INFO(logger, "quick lazy jumps example {} {} {} {} {} {} {} {}", "example2", 6LL, 4.0f, 7UL, 2, 5L, std::string_view("view2"), static_cast(9)); LOG_INFO(logger, "dog test logging quick {} {}", false, "example2"); LOG_INFO(logger, "example dog over lazy {} {} {} {} {} {} {} {} {} {}", 6LL, 2, 3.0, std::string_view("view2"), "example3", 4.0f, 8ULL, true, std::string("str2"), std::string("str1")); LOG_INFO(logger, "test example logging {} {} {} {}", 1, std::string("str1"), 6LL, false); LOG_INFO(logger, "logging over jumps lazy {} {} {} {} {} {} {} {} {}", true, 7UL, "example2", static_cast(9), "example3", std::string_view("view2"), 5L, std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "fox logging brown {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 2, false, static_cast(9), 3.0, "example2", std::string_view("view2"), static_cast(10), true, "example1"); LOG_INFO(logger, "over jumps logging {} {} {}", 5L, std::string("str2"), true); LOG_INFO(logger, "lazy fox example brown {}", std::string_view("view1")); LOG_INFO(logger, "test over quick {} {}", 8ULL, 5L); LOG_INFO(logger, "example jumps quick fox {}", 6LL); LOG_INFO(logger, "fox dog example quick {} {} {} {} {} {} {} {} {} {}", 5L, 7UL, "example2", 8ULL, 3.0, static_cast(9), 6LL, true, static_cast(10), "example1"); LOG_INFO(logger, "over test example dog {} {} {} {} {} {} {} {}", 2, 8ULL, 4.0f, "example1", static_cast(9), std::string("str2"), 5L, std::string_view("view1")); LOG_INFO(logger, "over dog test {} {}", 7UL, 2); LOG_INFO(logger, "brown fox logging {}", 7UL); LOG_INFO(logger, "fox jumps logging dog {} {} {} {} {} {} {} {}", 3.0, "example1", "example3", std::string_view("view2"), false, 4.0f, 5L, true); LOG_INFO(logger, "brown example logging {}", static_cast(10)); LOG_INFO(logger, "brown jumps logging over {} {} {} {} {} {}", 6LL, 1, 8ULL, "example2", std::string_view("view2"), "example3"); LOG_INFO(logger, "logging fox brown {} {} {} {} {}", 2, 8ULL, static_cast(9), 6LL, 3.0); LOG_INFO(logger, "lazy dog jumps fox {} {} {} {} {} {} {}", std::string_view("view2"), std::string("str2"), std::string_view("view1"), "example1", 1, false, 4.0f); LOG_INFO(logger, "brown quick dog {}", static_cast(10)); LOG_INFO(logger, "brown dog lazy {} {} {} {} {}", static_cast(10), 3.0, std::string_view("view2"), static_cast(9), 2); LOG_INFO(logger, "lazy fox quick {} {} {}", 5L, "example1", static_cast(10)); LOG_INFO(logger, "fox over quick {} {} {} {} {} {}", 4.0f, 6LL, std::string_view("view1"), "example2", 1, std::string_view("view2")); LOG_INFO(logger, "fox brown dog {} {} {} {} {} {} {}", false, 3.0, 4.0f, std::string_view("view2"), 1, 6LL, 5L); LOG_INFO(logger, "test brown jumps {} {} {} {} {}", true, 4.0f, static_cast(10), "example1", std::string("str1")); LOG_INFO(logger, "example fox test dog {} {}", std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "brown example quick {} {} {} {} {} {} {} {} {} {}", 2, 6LL, "example3", static_cast(9), std::string_view("view1"), false, 4.0f, std::string("str1"), 7UL, 1); LOG_INFO(logger, "example lazy over {} {} {} {} {} {}", static_cast(9), 5L, "example3", std::string("str1"), 7UL, std::string("str2")); LOG_INFO(logger, "quick logging fox {} {} {} {} {} {}", 5L, true, false, 2, std::string_view("view1"), 4.0f); LOG_INFO(logger, "logging lazy dog {} {} {} {} {} {}", std::string_view("view1"), 4.0f, "example1", "example3", false, std::string("str2")); LOG_INFO(logger, "fox dog over test {} {} {} {} {} {} {} {} {}", std::string("str2"), 5L, 3.0, "example3", static_cast(9), true, 6LL, 8ULL, 1); LOG_INFO(logger, "dog lazy jumps {}", static_cast(9)); LOG_INFO(logger, "test example dog {} {} {} {} {} {} {} {} {} {}", static_cast(10), std::string("str2"), 7UL, std::string("str1"), true, static_cast(9), std::string_view("view2"), false, 1, 8ULL); LOG_INFO(logger, "fox jumps dog test {} {} {} {} {}", 1, 8ULL, std::string("str1"), "example2", std::string_view("view2")); LOG_INFO(logger, "example brown fox quick {} {}", static_cast(9), false); LOG_INFO(logger, "over quick dog {} {} {} {} {}", 5L, 1, 8ULL, 7UL, 3.0); LOG_INFO(logger, "brown test over quick {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, 4.0f, 2, false, "example3", 7UL, static_cast(9), true, 5L); LOG_INFO(logger, "brown lazy over {} {} {} {} {} {}", std::string("str2"), 7UL, static_cast(9), true, 8ULL, 2); LOG_INFO(logger, "brown lazy fox {} {} {} {} {} {} {} {}", 7UL, 4.0f, static_cast(9), 1, 6LL, false, "example2", std::string_view("view1")); LOG_INFO(logger, "fox logging jumps quick {} {}", 6LL, 5L); LOG_INFO(logger, "quick fox brown {} {} {} {} {}", std::string_view("view1"), std::string_view("view2"), "example1", 2, "example2"); LOG_INFO(logger, "example quick over brown {} {} {}", 8ULL, static_cast(10), std::string_view("view1")); LOG_INFO(logger, "quick over lazy {} {} {} {} {} {}", 7UL, 2, static_cast(10), 1, 3.0, 8ULL); LOG_INFO(logger, "logging fox test brown {} {} {} {} {}", false, 8ULL, 1, 5L, std::string_view("view2")); LOG_INFO(logger, "fox over dog test {}", std::string_view("view2")); LOG_INFO(logger, "brown jumps logging {} {} {} {} {}", 4.0f, 8ULL, true, std::string_view("view1"), static_cast(9)); LOG_INFO(logger, "quick over brown jumps {} {} {} {} {} {}", "example2", "example3", 7UL, false, 8ULL, 5L); LOG_INFO(logger, "test dog example over {} {} {} {} {} {}", 2, 1, static_cast(9), "example3", std::string_view("view2"), std::string_view("view1")); LOG_INFO(logger, "fox logging lazy over {} {} {} {}", "example2", std::string("str1"), 5L, 3.0); LOG_INFO(logger, "logging fox test {} {} {} {}", false, static_cast(9), static_cast(10), "example3"); LOG_INFO(logger, "brown logging dog example {} {} {} {} {} {} {} {} {}", "example2", std::string_view("view1"), std::string("str1"), "example3", std::string_view("view2"), "example1", false, static_cast(10), 5L); LOG_INFO(logger, "dog test example over {}", "example1"); LOG_INFO(logger, "over jumps logging test {} {} {} {}", true, 4.0f, std::string("str2"), false); LOG_INFO(logger, "brown example test logging {} {} {} {} {} {}", 3.0, 6LL, std::string("str2"), static_cast(10), "example2", std::string_view("view1")); LOG_INFO(logger, "example over dog quick {} {} {} {} {}", 1, 2, false, "example1", "example3"); LOG_INFO(logger, "test dog example {} {} {} {} {} {} {} {} {} {}", true, "example2", "example3", std::string("str2"), 1, static_cast(10), std::string_view("view1"), "example1", 7UL, false); LOG_INFO(logger, "dog example lazy test {} {} {} {}", "example2", std::string_view("view2"), 5L, 7UL); LOG_INFO(logger, "logging over dog {}", std::string("str1")); LOG_INFO(logger, "logging jumps test example {} {} {} {} {} {} {}", "example2", 8ULL, std::string_view("view1"), "example1", static_cast(10), 5L, "example3"); LOG_INFO(logger, "quick dog example {} {} {} {} {} {} {} {} {} {}", std::string("str1"), std::string_view("view2"), true, 8ULL, std::string_view("view1"), 7UL, static_cast(9), 3.0, static_cast(10), std::string("str2")); LOG_INFO(logger, "brown quick over {} {}", 7UL, 2); LOG_INFO(logger, "over lazy fox test {} {}", 8ULL, std::string("str2")); LOG_INFO(logger, "example test brown jumps {} {}", std::string("str2"), 4.0f); LOG_INFO(logger, "quick example lazy {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), false, 2, static_cast(9), 3.0, "example3", std::string_view("view1"), "example1", true, 1); LOG_INFO(logger, "dog fox test {} {} {} {} {} {} {}", 3.0, false, static_cast(9), static_cast(10), 6LL, 1, "example3"); LOG_INFO(logger, "test quick fox logging {} {} {} {}", true, 1, 7UL, 2); LOG_INFO(logger, "brown example dog {} {} {} {} {}", std::string("str1"), 5L, "example1", std::string("str2"), "example2"); LOG_INFO(logger, "logging test dog {} {} {} {} {} {} {}", 5L, static_cast(9), 8ULL, false, 4.0f, 6LL, std::string("str2")); LOG_INFO(logger, "jumps brown quick {} {} {} {} {}", "example3", "example2", std::string("str2"), 4.0f, 5L); LOG_INFO(logger, "test over dog {} {} {} {} {} {} {} {} {} {}", 6LL, 2, "example3", std::string_view("view1"), static_cast(9), 1, 5L, "example1", 4.0f, "example2"); LOG_INFO(logger, "jumps test quick {} {} {} {} {} {} {}", false, "example2", 8ULL, std::string_view("view1"), static_cast(10), static_cast(9), std::string("str1")); LOG_INFO(logger, "test logging fox {} {} {} {} {} {} {} {} {}", static_cast(9), "example3", std::string_view("view1"), true, std::string("str2"), 7UL, static_cast(10), std::string("str1"), 8ULL); LOG_INFO(logger, "lazy dog over {} {} {} {} {} {} {} {} {}", 4.0f, 1, "example3", std::string("str2"), true, 3.0, 5L, "example2", std::string_view("view2")); LOG_INFO(logger, "test lazy dog {} {} {} {}", true, std::string_view("view2"), 6LL, "example1"); LOG_INFO(logger, "jumps over logging example {} {} {} {} {}", std::string_view("view1"), "example2", static_cast(10), std::string("str2"), 3.0); LOG_INFO(logger, "example over jumps {} {}", std::string("str1"), "example3"); LOG_INFO(logger, "quick brown test {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), std::string("str1"), 6LL, 8ULL, "example1", std::string_view("view2"), "example3", 2, 7UL, 5L); LOG_INFO(logger, "dog lazy quick over {} {} {} {} {} {} {} {}", 5L, 8ULL, true, false, std::string("str1"), std::string_view("view2"), "example1", static_cast(10)); LOG_INFO(logger, "jumps test dog {} {} {}", "example1", 4.0f, static_cast(10)); LOG_INFO(logger, "example test lazy {} {} {} {} {} {} {} {} {}", "example1", true, std::string_view("view2"), std::string("str1"), 7UL, 6LL, 8ULL, static_cast(10), "example2"); LOG_INFO(logger, "fox brown quick over {} {} {} {}", 6LL, std::string_view("view1"), "example3", 4.0f); LOG_INFO(logger, "dog jumps test brown {}", true); LOG_INFO(logger, "quick dog test {} {} {} {}", static_cast(9), 3.0, 2, static_cast(10)); LOG_INFO(logger, "lazy over brown {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 8ULL, 6LL, 7UL, 4.0f, false, 5L, 3.0, std::string_view("view2"), "example1"); LOG_INFO(logger, "quick jumps fox {} {} {} {}", static_cast(9), 2, 8ULL, std::string_view("view1")); LOG_INFO(logger, "quick lazy test brown {} {} {} {} {}", 6LL, false, "example2", 2, 1); LOG_INFO(logger, "test lazy logging dog {} {} {} {}", 2, static_cast(9), std::string_view("view2"), false); LOG_INFO(logger, "quick lazy logging {} {} {} {} {} {} {} {} {}", std::string_view("view1"), static_cast(9), 2, std::string("str2"), 7UL, 3.0, std::string_view("view2"), 4.0f, 6LL); LOG_INFO(logger, "over lazy fox test {} {} {} {} {} {} {} {}", "example2", static_cast(10), std::string("str1"), "example3", 1, 2, true, std::string_view("view2")); LOG_INFO(logger, "brown logging over {} {} {} {}", 1, false, 8ULL, true); LOG_INFO(logger, "dog brown jumps quick {} {} {} {} {}", std::string_view("view1"), true, 7UL, std::string_view("view2"), 5L); LOG_INFO(logger, "jumps dog fox logging {} {} {} {} {} {} {} {}", "example1", 6LL, 1, static_cast(9), 3.0, 2, std::string("str2"), 7UL); LOG_INFO(logger, "logging lazy dog test {} {} {} {}", 5L, "example3", std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "over fox test {} {} {} {}", 4.0f, false, "example1", true); LOG_INFO(logger, "quick logging jumps over {} {} {} {} {} {} {} {}", false, true, std::string_view("view1"), 2, "example3", 3.0, "example2", std::string("str1")); LOG_INFO(logger, "test brown fox {} {}", std::string_view("view2"), 7UL); LOG_INFO(logger, "example lazy dog {} {} {} {} {} {} {} {}", "example2", 4.0f, std::string("str2"), std::string("str1"), 8ULL, 7UL, std::string_view("view2"), 2); LOG_INFO(logger, "example logging fox test {} {} {} {} {} {} {} {}", true, static_cast(9), 2, 7UL, 3.0, "example2", std::string("str2"), std::string("str1")); LOG_INFO(logger, "brown jumps logging test {} {} {}", 6LL, true, std::string_view("view1")); LOG_INFO(logger, "fox lazy jumps {} {} {} {}", "example3", std::string("str1"), true, 3.0); LOG_INFO(logger, "fox test over quick {} {} {} {} {} {} {} {}", 8ULL, 4.0f, std::string("str1"), 3.0, 7UL, std::string_view("view2"), "example2", static_cast(10)); LOG_INFO(logger, "brown dog over logging {} {} {} {} {} {} {}", 4.0f, 7UL, "example3", std::string("str2"), 3.0, 8ULL, "example2"); LOG_INFO(logger, "lazy dog brown logging {} {}", 4.0f, 8ULL); LOG_INFO(logger, "quick over jumps lazy {} {} {} {} {} {} {} {} {} {}", std::string("str2"), "example2", 7UL, std::string("str1"), std::string_view("view2"), "example3", static_cast(9), 2, "example1", true); LOG_INFO(logger, "jumps logging lazy over {} {} {} {} {}", true, std::string_view("view2"), 3.0, "example3", static_cast(10)); LOG_INFO(logger, "brown quick example {} {} {} {}", true, "example1", std::string("str1"), 2); LOG_INFO(logger, "over fox quick lazy {} {} {}", 5L, 3.0, std::string_view("view1")); LOG_INFO(logger, "fox logging example {}", "example2"); LOG_INFO(logger, "over dog test {} {} {} {} {} {} {}", 4.0f, static_cast(10), 1, 7UL, true, false, 6LL); LOG_INFO(logger, "quick logging lazy dog {} {} {} {} {} {} {} {} {} {}", static_cast(10), true, "example3", 5L, 8ULL, 1, static_cast(9), std::string("str1"), "example2", 6LL); LOG_INFO(logger, "brown jumps lazy test {} {} {} {} {} {} {}", 8ULL, "example3", 6LL, std::string_view("view2"), std::string("str2"), "example2", false); LOG_INFO(logger, "quick example test lazy {} {} {} {} {}", true, false, "example2", 6LL, "example3"); LOG_INFO(logger, "brown jumps logging {} {} {} {} {} {}", static_cast(10), 3.0, 8ULL, "example3", true, 4.0f); LOG_INFO(logger, "fox jumps logging {}", "example3"); LOG_INFO(logger, "jumps test example {} {}", std::string("str2"), 1); LOG_INFO(logger, "quick example jumps lazy {} {} {} {} {} {} {} {} {} {}", 5L, 6LL, static_cast(9), 4.0f, "example3", "example2", 1, std::string("str2"), std::string_view("view2"), false); LOG_INFO(logger, "fox quick over logging {} {} {} {} {} {} {} {} {}", 1, std::string_view("view2"), 8ULL, false, 3.0, std::string_view("view1"), "example1", true, 7UL); LOG_INFO(logger, "brown logging test fox {} {} {} {} {} {} {} {}", std::string("str1"), 5L, static_cast(9), 7UL, 6LL, std::string_view("view2"), "example2", 8ULL); LOG_INFO(logger, "brown example quick test {} {} {}", std::string_view("view2"), "example2", std::string_view("view1")); LOG_INFO(logger, "logging example test brown {} {} {} {} {} {}", std::string_view("view2"), "example3", std::string("str2"), 8ULL, 3.0, std::string_view("view1")); LOG_INFO(logger, "over quick fox dog {} {} {} {} {} {}", std::string("str2"), 5L, 6LL, "example3", 8ULL, std::string_view("view2")); LOG_INFO(logger, "test example brown {} {} {} {} {} {} {} {} {} {}", "example1", 7UL, 6LL, "example2", 2, std::string("str1"), 1, false, 4.0f, 5L); LOG_INFO(logger, "over test logging {} {} {} {} {} {} {} {} {} {}", static_cast(10), 5L, "example3", static_cast(9), 6LL, std::string_view("view1"), 2, "example1", 3.0, 7UL); LOG_INFO(logger, "logging over dog {} {}", std::string_view("view1"), 6LL); LOG_INFO(logger, "jumps test example over {} {} {}", 5L, 7UL, "example1"); LOG_INFO(logger, "fox test over {}", 5L); LOG_INFO(logger, "quick jumps over brown {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view2"), 1, static_cast(9), std::string_view("view1"), true, false, 8ULL, static_cast(10)); LOG_INFO(logger, "over test jumps example {} {} {} {} {} {}", std::string("str2"), 1, std::string_view("view1"), "example2", std::string_view("view2"), 6LL); LOG_INFO(logger, "fox brown test lazy {} {} {} {}", static_cast(10), 2, std::string("str1"), "example3"); LOG_INFO(logger, "brown test jumps lazy {} {} {}", 7UL, std::string("str2"), 1); LOG_INFO(logger, "over jumps brown dog {} {} {}", 7UL, std::string("str2"), static_cast(9)); LOG_INFO(logger, "brown test example {} {} {} {} {} {} {}", 5L, static_cast(10), "example3", 7UL, "example2", std::string_view("view1"), 6LL); LOG_INFO(logger, "test brown dog {} {} {} {} {} {} {}", 1, 2, 6LL, 8ULL, true, "example1", 5L); LOG_INFO(logger, "lazy fox over {} {} {} {} {} {} {} {} {}", std::string_view("view1"), true, std::string("str2"), 4.0f, 3.0, "example2", 1, std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "dog over jumps {} {}", "example2", 3.0); LOG_INFO(logger, "test quick jumps dog {} {} {} {} {} {}", std::string("str1"), std::string("str2"), 5L, std::string_view("view2"), 3.0, 4.0f); LOG_INFO(logger, "logging over example {} {} {} {} {}", static_cast(10), 4.0f, 5L, 2, "example2"); LOG_INFO(logger, "dog example jumps {} {} {}", "example1", static_cast(10), 8ULL); LOG_INFO(logger, "example dog fox logging {} {} {} {}", 5L, std::string("str2"), "example3", "example2"); LOG_INFO(logger, "fox dog test lazy {} {} {} {} {} {} {}", "example3", std::string("str1"), "example2", 1, "example1", std::string_view("view2"), false); LOG_INFO(logger, "fox logging lazy quick {}", 2); LOG_INFO(logger, "test quick over {}", std::string_view("view2")); LOG_INFO(logger, "example logging jumps dog {} {}", std::string("str1"), std::string_view("view2")); LOG_INFO(logger, "over lazy logging {} {} {} {} {} {}", 7UL, 6LL, static_cast(9), "example1", std::string_view("view1"), "example3"); LOG_INFO(logger, "logging example dog {} {} {} {} {} {} {} {} {} {}", 3.0, static_cast(10), 5L, "example3", 2, static_cast(9), false, std::string("str1"), 6LL, 4.0f); LOG_INFO(logger, "example quick lazy {} {}", static_cast(10), false); LOG_INFO(logger, "example fox over logging {} {} {}", "example2", static_cast(9), "example1"); LOG_INFO(logger, "logging jumps brown {} {} {} {} {} {} {} {} {} {}", 5L, 2, 6LL, 4.0f, "example2", std::string_view("view2"), 3.0, static_cast(10), "example3", std::string_view("view1")); LOG_INFO(logger, "quick logging example fox {}", 2); LOG_INFO(logger, "example over quick {} {} {} {} {} {} {}", 6LL, 1, 5L, 2, 4.0f, 8ULL, "example3"); LOG_INFO(logger, "quick lazy test example {} {} {} {} {} {} {}", 4.0f, std::string("str2"), 2, 7UL, false, "example2", 1); LOG_INFO(logger, "dog jumps fox lazy {} {} {} {} {} {}", true, 3.0, std::string("str2"), false, std::string("str1"), 5L); LOG_INFO(logger, "brown quick dog jumps {} {} {}", 6LL, 4.0f, false); LOG_INFO(logger, "test lazy over brown {} {} {}", std::string("str2"), static_cast(9), "example2"); LOG_INFO(logger, "fox example quick jumps {} {} {} {}", 6LL, std::string("str2"), 2, 8ULL); LOG_INFO(logger, "logging brown dog over {} {} {} {}", 4.0f, 2, std::string_view("view2"), 6LL); LOG_INFO(logger, "over fox brown lazy {} {} {} {} {} {} {} {}", static_cast(10), 4.0f, true, 7UL, 5L, "example2", std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "fox quick lazy {} {} {} {} {} {} {} {} {}", "example1", std::string_view("view2"), true, 7UL, 2, std::string_view("view1"), static_cast(9), std::string("str1"), std::string("str2")); LOG_INFO(logger, "test brown example fox {} {} {} {} {} {} {} {} {} {}", 1, static_cast(9), false, true, 5L, std::string("str2"), "example3", 8ULL, 6LL, 7UL); LOG_INFO(logger, "dog lazy logging example {} {} {} {} {} {}", 5L, static_cast(10), 3.0, 1, true, 8ULL); LOG_INFO(logger, "logging quick fox test {} {} {} {} {} {} {} {} {}", true, false, std::string("str1"), 7UL, static_cast(9), static_cast(10), 5L, "example3", std::string("str2")); LOG_INFO(logger, "test quick over brown {} {}", false, "example3"); LOG_INFO(logger, "lazy quick over test {} {} {} {} {} {} {}", std::string("str1"), static_cast(9), std::string("str2"), std::string_view("view1"), 8ULL, 7UL, 6LL); LOG_INFO(logger, "fox brown example {} {} {} {} {} {} {}", 7UL, static_cast(10), 6LL, true, false, "example2", std::string("str2")); LOG_INFO(logger, "brown logging quick {} {} {} {} {} {} {} {} {} {}", "example3", 4.0f, 5L, true, "example1", "example2", static_cast(9), 2, 6LL, 1); LOG_INFO(logger, "test dog jumps {} {}", "example2", 4.0f); LOG_INFO(logger, "brown test dog {} {}", 5L, 3.0); LOG_INFO(logger, "dog jumps test {} {} {} {} {}", 8ULL, std::string("str1"), 6LL, 1, false); LOG_INFO(logger, "example over jumps {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, 2, "example1", 5L, 6LL, std::string_view("view2"), 4.0f, static_cast(9), 8ULL); LOG_INFO(logger, "quick logging brown jumps {} {} {} {} {}", 7UL, 1, static_cast(10), true, "example3"); LOG_INFO(logger, "test dog fox brown {} {} {} {} {} {} {} {}", std::string_view("view2"), 6LL, 7UL, std::string("str1"), static_cast(9), true, std::string_view("view1"), false); LOG_INFO(logger, "over lazy brown {} {} {} {} {} {} {}", "example3", 8ULL, std::string_view("view1"), false, std::string("str1"), std::string_view("view2"), "example2"); LOG_INFO(logger, "dog over logging lazy {} {} {} {} {} {} {} {}", "example1", 4.0f, "example3", true, 8ULL, std::string("str2"), std::string_view("view1"), 3.0); LOG_INFO(logger, "logging over dog quick {} {} {} {} {} {}", 5L, std::string("str2"), 7UL, "example3", std::string("str1"), 4.0f); LOG_INFO(logger, "dog example test {} {} {} {}", static_cast(10), std::string("str1"), "example2", std::string_view("view2")); LOG_INFO(logger, "quick example jumps {} {} {} {} {}", 1, 7UL, 3.0, "example3", 6LL); LOG_INFO(logger, "quick brown dog {} {} {} {} {} {} {} {} {}", std::string_view("view2"), false, 6LL, static_cast(10), 5L, "example2", 8ULL, 7UL, true); LOG_INFO(logger, "example brown test quick {} {} {}", 3.0, 2, static_cast(10)); LOG_INFO(logger, "test over fox {} {} {} {}", "example3", "example1", true, static_cast(9)); LOG_INFO(logger, "logging quick example {} {} {} {} {}", static_cast(9), 5L, std::string_view("view1"), "example1", 2); LOG_INFO(logger, "example brown over {} {} {} {} {} {}", std::string_view("view2"), std::string("str2"), 2, 7UL, std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "dog test lazy fox {} {} {} {} {} {} {}", std::string("str2"), 8ULL, 6LL, 2, 4.0f, "example3", false); LOG_INFO(logger, "test brown dog {}", false); LOG_INFO(logger, "jumps example lazy {}", 4.0f); LOG_INFO(logger, "over lazy jumps logging {} {} {} {} {} {} {} {} {} {}", 8ULL, static_cast(10), 3.0, std::string_view("view2"), false, true, 5L, 4.0f, static_cast(9), "example1"); LOG_INFO(logger, "fox lazy brown jumps {} {} {} {} {} {} {}", std::string("str2"), static_cast(10), 5L, 1, "example2", 4.0f, false); LOG_INFO(logger, "example brown logging jumps {} {} {} {} {} {} {} {}", 6LL, std::string_view("view1"), 2, false, static_cast(9), static_cast(10), "example1", 4.0f); LOG_INFO(logger, "fox test brown {} {} {} {} {}", static_cast(9), 3.0, 8ULL, 5L, 4.0f); LOG_INFO(logger, "over logging dog test {} {} {}", std::string_view("view1"), 8ULL, static_cast(10)); LOG_INFO(logger, "brown dog jumps test {} {} {}", 3.0, "example2", 5L); LOG_INFO(logger, "jumps example lazy {} {}", "example1", false); LOG_INFO(logger, "lazy dog test {} {} {} {}", std::string("str2"), static_cast(10), false, static_cast(9)); LOG_INFO(logger, "test fox lazy logging {} {}", static_cast(10), 8ULL); LOG_INFO(logger, "logging jumps fox {} {} {}", true, 3.0, 5L); LOG_INFO(logger, "quick example lazy brown {} {} {} {} {} {} {} {} {} {}", "example1", true, 3.0, 7UL, 8ULL, std::string("str2"), std::string("str1"), 4.0f, "example2", std::string_view("view2")); LOG_INFO(logger, "brown example over lazy {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, 4.0f, "example3", std::string("str2"), 8ULL, 6LL); LOG_INFO(logger, "example test brown quick {} {} {} {} {} {}", "example2", 7UL, 4.0f, static_cast(9), "example1", 2); LOG_INFO(logger, "over logging example jumps {} {} {} {} {} {}", static_cast(10), 6LL, 4.0f, 7UL, 3.0, true); LOG_INFO(logger, "example fox lazy test {} {} {} {} {} {}", static_cast(9), 6LL, 7UL, 1, 4.0f, 8ULL); LOG_INFO(logger, "brown lazy quick {} {} {} {} {} {} {}", static_cast(9), 6LL, true, static_cast(10), "example2", false, 5L); LOG_INFO(logger, "quick example lazy {}", std::string_view("view2")); LOG_INFO(logger, "fox example over {} {} {}", static_cast(10), std::string_view("view2"), 5L); LOG_INFO(logger, "dog over fox {} {} {} {}", 1, std::string_view("view2"), 2, std::string("str2")); LOG_INFO(logger, "test jumps quick dog {} {} {} {} {} {} {}", std::string("str1"), 1, "example3", 4.0f, static_cast(10), 8ULL, "example2"); LOG_INFO(logger, "example jumps lazy {} {} {} {} {}", std::string("str2"), "example2", static_cast(9), 6LL, 8ULL); LOG_INFO(logger, "quick jumps lazy example {} {} {} {} {} {} {}", 4.0f, 7UL, false, static_cast(10), "example2", static_cast(9), 1); LOG_INFO(logger, "dog quick brown {} {} {} {} {}", false, 4.0f, "example3", 7UL, true); LOG_INFO(logger, "quick brown jumps {} {} {} {} {} {} {}", 2, 3.0, "example3", 1, 8ULL, static_cast(10), std::string("str1")); LOG_INFO(logger, "test lazy dog quick {} {} {} {} {}", std::string("str2"), static_cast(9), 8ULL, false, static_cast(10)); LOG_INFO(logger, "over quick lazy fox {} {}", "example1", std::string_view("view1")); LOG_INFO(logger, "quick over lazy {} {} {} {} {} {}", false, static_cast(9), 2, 1, 3.0, std::string("str1")); LOG_INFO(logger, "fox lazy logging {} {} {} {} {} {} {}", 4.0f, "example3", true, false, std::string_view("view2"), static_cast(9), std::string("str1")); LOG_INFO(logger, "example jumps dog fox {} {} {} {}", std::string_view("view1"), static_cast(10), std::string("str1"), 8ULL); LOG_INFO(logger, "dog lazy test logging {} {} {} {} {} {} {} {}", std::string_view("view2"), 8ULL, 2, std::string("str1"), static_cast(9), "example3", std::string("str2"), true); LOG_INFO(logger, "logging dog jumps {} {} {} {} {} {} {} {} {} {}", "example2", 1, false, 6LL, 3.0, static_cast(10), std::string_view("view2"), 4.0f, true, "example3"); LOG_INFO(logger, "example dog logging quick {} {} {} {} {} {}", false, "example3", 4.0f, std::string("str1"), 7UL, 5L); LOG_INFO(logger, "test fox quick brown {}", std::string_view("view2")); LOG_INFO(logger, "example quick logging {} {} {} {} {} {} {}", static_cast(10), std::string("str1"), 2, "example2", std::string("str2"), std::string_view("view2"), "example1"); LOG_INFO(logger, "jumps fox quick test {} {} {} {} {} {} {} {}", 4.0f, 5L, "example2", 3.0, static_cast(9), 1, 8ULL, std::string_view("view1")); LOG_INFO(logger, "logging lazy jumps quick {} {} {} {} {}", 7UL, "example2", std::string_view("view2"), 4.0f, 3.0); LOG_INFO(logger, "test logging lazy over {} {} {} {} {} {} {} {}", "example1", std::string_view("view2"), 6LL, 5L, std::string("str1"), 8ULL, 3.0, static_cast(9)); LOG_INFO(logger, "logging test fox {}", 8ULL); LOG_INFO(logger, "dog lazy jumps {} {} {} {} {} {} {}", 3.0, 7UL, "example2", 1, std::string_view("view2"), 6LL, std::string_view("view1")); LOG_INFO(logger, "dog over fox jumps {} {} {} {} {} {} {} {}", static_cast(9), std::string_view("view2"), 2, "example2", 6LL, 8ULL, std::string("str2"), std::string_view("view1")); LOG_INFO(logger, "logging quick lazy {} {} {} {} {}", 8ULL, std::string("str1"), 4.0f, std::string("str2"), "example2"); LOG_INFO(logger, "dog test fox {} {} {} {} {} {} {} {} {}", "example1", std::string("str2"), 1, 3.0, std::string_view("view2"), 7UL, false, 8ULL, 2); LOG_INFO(logger, "over dog quick jumps {} {} {} {} {} {} {} {} {}", std::string("str2"), 8ULL, "example3", 3.0, false, true, 2, std::string_view("view2"), static_cast(9)); LOG_INFO(logger, "quick logging brown {} {} {} {} {}", "example3", static_cast(10), 8ULL, "example1", false); LOG_INFO(logger, "lazy example logging fox {} {} {} {} {} {} {}", 7UL, 6LL, 3.0, false, 5L, std::string("str2"), true); LOG_INFO(logger, "fox over brown lazy {} {} {} {} {}", 3.0, 6LL, true, std::string_view("view2"), "example3"); LOG_INFO(logger, "test fox quick {} {} {} {} {} {} {} {} {}", "example2", 4.0f, std::string("str2"), static_cast(10), 6LL, 5L, static_cast(9), false, true); LOG_INFO(logger, "brown quick lazy dog {} {} {} {} {} {}", static_cast(9), "example1", 2, 4.0f, 8ULL, 7UL); LOG_INFO(logger, "example dog logging {} {}", true, "example1"); LOG_INFO(logger, "logging example jumps over {} {} {} {}", 4.0f, static_cast(10), "example2", static_cast(9)); LOG_INFO(logger, "lazy brown example test {} {} {} {} {} {}", true, 1, static_cast(9), 8ULL, 3.0, std::string("str1")); LOG_INFO(logger, "test example jumps {} {} {} {} {}", "example3", 4.0f, true, std::string_view("view1"), 6LL); LOG_INFO(logger, "fox quick over {} {} {} {} {} {} {}", 3.0, std::string_view("view1"), 2, 8ULL, 7UL, true, "example3"); LOG_INFO(logger, "test logging jumps brown {}", 1); LOG_INFO(logger, "jumps lazy logging quick {}", "example2"); LOG_INFO(logger, "lazy quick dog logging {} {} {} {} {} {}", "example3", 5L, "example1", 3.0, std::string("str2"), std::string("str1")); LOG_INFO(logger, "example test logging {} {}", std::string_view("view2"), "example1"); LOG_INFO(logger, "brown logging dog fox {} {} {} {} {} {} {} {} {} {}", 1, static_cast(9), "example2", 7UL, 8ULL, std::string("str2"), "example3", 5L, 2, 6LL); LOG_INFO(logger, "logging lazy dog {} {} {}", std::string("str1"), "example2", "example1"); LOG_INFO(logger, "test lazy fox brown {} {} {}", static_cast(9), std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "over test example fox {}", std::string_view("view2")); LOG_INFO(logger, "fox test lazy {}", std::string("str2")); LOG_INFO(logger, "over test dog {} {} {} {}", std::string("str2"), 7UL, std::string("str1"), 8ULL); LOG_INFO(logger, "fox example brown {} {} {} {} {} {} {} {} {}", true, std::string("str1"), 1, std::string_view("view1"), "example2", "example1", std::string_view("view2"), 6LL, 7UL); LOG_INFO(logger, "test jumps fox example {} {} {} {} {} {} {} {}", static_cast(10), "example3", static_cast(9), 5L, std::string("str2"), 8ULL, true, 7UL); LOG_INFO(logger, "fox jumps over {} {} {} {} {} {} {} {}", 5L, std::string_view("view1"), 4.0f, 8ULL, "example2", std::string("str1"), "example3", static_cast(9)); LOG_INFO(logger, "jumps fox logging lazy {} {} {} {} {} {} {} {}", "example2", 3.0, 5L, std::string("str2"), 2, 6LL, 8ULL, 1); LOG_INFO(logger, "quick lazy dog example {}", static_cast(9)); LOG_INFO(logger, "jumps example lazy {} {} {} {} {} {} {} {} {}", 1, 3.0, 4.0f, true, 5L, 8ULL, "example3", std::string_view("view1"), 7UL); LOG_INFO(logger, "over test quick {} {} {}", static_cast(9), 2, 5L); LOG_INFO(logger, "jumps fox lazy {} {} {} {} {}", "example2", 3.0, "example3", std::string_view("view1"), std::string_view("view2")); LOG_INFO(logger, "jumps dog test {} {} {} {} {} {} {}", false, 7UL, std::string("str2"), 8ULL, std::string_view("view2"), 6LL, std::string("str1")); LOG_INFO(logger, "fox quick brown {} {} {} {}", 7UL, "example2", std::string_view("view1"), 5L); LOG_INFO(logger, "over quick jumps {} {} {} {} {} {} {} {} {}", 4.0f, 6LL, static_cast(9), 3.0, "example2", std::string("str1"), "example3", "example1", std::string_view("view1")); LOG_INFO(logger, "lazy jumps over fox {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 1, 3.0, static_cast(10), std::string("str2"), "example2", static_cast(9), true, 6LL); LOG_INFO(logger, "jumps dog brown example {} {} {} {} {} {}", 8ULL, 6LL, std::string("str2"), "example2", false, 4.0f); LOG_INFO(logger, "test fox jumps logging {} {} {} {} {} {} {} {} {} {}", false, "example2", 4.0f, std::string("str1"), "example3", true, std::string_view("view2"), 1, std::string("str2"), static_cast(10)); LOG_INFO(logger, "logging test example over {}", false); LOG_INFO(logger, "jumps brown dog {}", 5L); LOG_INFO(logger, "dog lazy brown quick {} {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string("str1"), "example3", 8ULL, std::string_view("view1"), "example1", "example2", false, 6LL, static_cast(9)); LOG_INFO(logger, "lazy fox brown {} {} {}", std::string_view("view2"), static_cast(10), 5L); LOG_INFO(logger, "jumps brown lazy {} {} {} {} {} {} {}", std::string_view("view1"), static_cast(9), 1, 2, std::string("str1"), 4.0f, static_cast(10)); LOG_INFO(logger, "jumps lazy fox {} {} {} {} {} {} {} {} {} {}", static_cast(10), 3.0, 2, std::string("str2"), 6LL, "example2", "example3", true, 4.0f, std::string("str1")); LOG_INFO(logger, "test logging dog {} {} {} {} {} {}", false, std::string_view("view2"), 3.0, 6LL, "example1", 2); LOG_INFO(logger, "dog logging example fox {} {} {} {} {} {} {} {} {}", false, static_cast(9), std::string("str1"), static_cast(10), 6LL, true, 1, 3.0, std::string("str2")); LOG_INFO(logger, "fox test lazy {} {} {} {} {} {} {}", static_cast(10), std::string("str2"), 2, true, 3.0, static_cast(9), std::string_view("view2")); LOG_INFO(logger, "dog test over {} {} {}", std::string_view("view1"), 2, static_cast(9)); LOG_INFO(logger, "fox example test {} {} {} {} {} {} {}", 5L, std::string_view("view1"), "example3", 8ULL, std::string("str1"), true, 7UL); LOG_INFO(logger, "dog over quick {} {} {} {}", "example3", 2, std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "lazy example over {} {}", 4.0f, true); LOG_INFO(logger, "over brown jumps fox {} {} {} {} {} {} {} {}", "example1", std::string_view("view2"), 2, static_cast(9), std::string("str2"), 5L, std::string("str1"), 1); LOG_INFO(logger, "over dog fox quick {} {} {} {} {} {}", static_cast(9), false, std::string("str2"), 8ULL, "example2", "example3"); LOG_INFO(logger, "fox quick jumps example {} {} {} {} {}", 2, "example3", static_cast(9), std::string_view("view2"), std::string("str1")); LOG_INFO(logger, "test fox logging {} {} {} {} {} {}", "example2", 4.0f, static_cast(10), 6LL, "example3", std::string("str1")); LOG_INFO(logger, "quick logging lazy {} {} {} {} {} {} {} {} {}", 1, 8ULL, 4.0f, 6LL, std::string("str2"), std::string_view("view1"), 2, true, false); LOG_INFO(logger, "example lazy quick fox {} {} {} {} {} {} {} {} {} {}", false, 7UL, 3.0, true, 6LL, 5L, 8ULL, 1, "example1", std::string_view("view1")); LOG_INFO(logger, "jumps example over {} {} {} {} {}", true, 2, std::string("str1"), std::string_view("view2"), 3.0); LOG_INFO(logger, "test dog jumps fox {} {} {} {} {}", "example2", "example1", 4.0f, 5L, 3.0); LOG_INFO(logger, "brown over jumps {}", 8ULL); LOG_INFO(logger, "test jumps quick {} {} {}", 1, 5L, "example1"); LOG_INFO(logger, "example test jumps brown {} {} {}", static_cast(10), 5L, "example2"); LOG_INFO(logger, "dog brown test lazy {} {} {} {} {} {} {}", std::string("str2"), 7UL, "example2", 5L, 2, false, "example3"); LOG_INFO(logger, "example fox dog over {} {} {} {} {} {} {} {}", true, 3.0, 8ULL, "example3", 1, std::string("str2"), static_cast(9), 7UL); LOG_INFO(logger, "over dog jumps {} {}", std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "lazy quick jumps {} {} {} {} {} {} {}", static_cast(9), 1, 2, false, 4.0f, std::string_view("view1"), 3.0); LOG_INFO(logger, "over quick test logging {} {} {} {} {} {} {} {} {}", 2, std::string("str1"), 7UL, 5L, "example2", true, "example1", std::string("str2"), 4.0f); LOG_INFO(logger, "over test logging {} {} {} {} {} {} {} {} {}", 5L, 4.0f, std::string_view("view1"), std::string_view("view2"), 3.0, std::string("str1"), "example3", 8ULL, 1); LOG_INFO(logger, "test lazy logging dog {} {}", 7UL, "example3"); LOG_INFO(logger, "example fox lazy logging {} {} {} {} {} {} {} {} {}", 1, 8ULL, 3.0, std::string_view("view2"), "example3", std::string_view("view1"), true, static_cast(10), "example2"); LOG_INFO(logger, "dog over test {} {} {}", 1, 8ULL, std::string_view("view1")); LOG_INFO(logger, "dog logging test brown {} {} {}", std::string_view("view1"), 5L, static_cast(10)); LOG_INFO(logger, "fox quick over example {} {} {}", static_cast(10), "example3", true); LOG_INFO(logger, "lazy jumps example {} {} {}", 8ULL, 3.0, true); LOG_INFO(logger, "quick logging test {} {} {} {} {} {} {} {}", 3.0, std::string_view("view1"), 1, true, std::string_view("view2"), static_cast(9), std::string("str2"), 4.0f); LOG_INFO(logger, "quick dog fox example {}", 5L); LOG_INFO(logger, "lazy fox brown {} {} {} {} {} {}", true, "example1", 3.0, "example3", 7UL, std::string("str1")); LOG_INFO(logger, "fox jumps quick test {} {} {} {} {}", std::string("str2"), std::string_view("view2"), static_cast(9), "example2", 6LL); LOG_INFO(logger, "brown logging fox {} {} {} {} {} {} {} {} {} {}", 2, std::string_view("view2"), "example2", std::string("str1"), "example1", 7UL, 6LL, false, 3.0, "example3"); LOG_INFO(logger, "dog lazy over logging {} {} {} {}", std::string("str2"), 1, std::string_view("view1"), std::string_view("view2")); LOG_INFO(logger, "dog test over {} {} {} {}", std::string_view("view2"), 5L, "example1", static_cast(10)); LOG_INFO(logger, "dog example quick logging {} {} {}", 3.0, std::string_view("view1"), 8ULL); LOG_INFO(logger, "dog lazy test {} {} {} {} {} {} {}", true, static_cast(9), std::string_view("view1"), 2, false, std::string("str2"), 5L); LOG_INFO(logger, "test jumps quick {} {} {}", std::string("str1"), 1, std::string_view("view1")); LOG_INFO(logger, "example lazy brown {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), 2, static_cast(10), 1, std::string_view("view2"), 8ULL); LOG_INFO(logger, "test example fox {} {} {} {} {} {} {}", "example1", "example3", true, 8ULL, static_cast(10), 6LL, false); LOG_INFO(logger, "test brown over fox {} {} {} {} {} {}", "example1", std::string_view("view1"), 8ULL, static_cast(9), 6LL, false); LOG_INFO(logger, "jumps dog test logging {} {}", "example1", 4.0f); LOG_INFO(logger, "fox quick lazy jumps {} {} {}", false, 6LL, 1); LOG_INFO(logger, "fox brown test lazy {} {} {} {} {} {} {}", static_cast(9), std::string_view("view2"), "example3", std::string("str2"), std::string_view("view1"), false, true); LOG_INFO(logger, "jumps fox brown lazy {} {} {} {} {} {} {} {}", static_cast(10), 2, "example1", true, static_cast(9), std::string_view("view2"), "example3", 6LL); LOG_INFO(logger, "logging lazy jumps test {} {} {} {} {}", 7UL, std::string_view("view2"), 8ULL, "example1", static_cast(9)); LOG_INFO(logger, "jumps logging test {} {} {} {} {} {} {} {}", 2, false, 5L, 6LL, 7UL, 8ULL, 4.0f, std::string("str2")); LOG_INFO(logger, "fox quick brown test {} {} {} {} {} {}", "example2", 7UL, static_cast(10), false, "example3", std::string_view("view2")); LOG_INFO(logger, "brown logging lazy {} {} {} {} {} {}", false, std::string_view("view1"), std::string("str1"), std::string_view("view2"), 3.0, "example1"); LOG_INFO(logger, "test fox dog {} {} {}", std::string_view("view2"), 6LL, static_cast(10)); LOG_INFO(logger, "dog over jumps {} {} {} {} {} {}", true, 3.0, "example1", "example3", 1, 2); LOG_INFO(logger, "fox example over {} {} {}", "example3", 8ULL, 6LL); LOG_INFO(logger, "logging test example {} {} {} {}", std::string_view("view1"), 7UL, 3.0, 2); LOG_INFO(logger, "jumps test dog {} {} {}", 1, 3.0, 2); LOG_INFO(logger, "brown test logging fox {} {} {} {} {} {} {} {}", 8ULL, 4.0f, 7UL, std::string("str2"), std::string_view("view1"), "example3", false, 6LL); LOG_INFO(logger, "quick dog over {} {} {} {} {} {} {} {}", true, 5L, 4.0f, "example1", false, "example2", static_cast(10), 3.0); LOG_INFO(logger, "over quick logging {} {} {}", 6LL, static_cast(10), 3.0); LOG_INFO(logger, "brown over lazy logging {} {} {} {} {} {}", "example2", "example1", 7UL, 4.0f, std::string_view("view2"), "example3"); LOG_INFO(logger, "lazy quick jumps {} {} {} {} {} {} {}", 3.0, 5L, false, 6LL, std::string_view("view2"), "example1", static_cast(10)); LOG_INFO(logger, "over brown dog logging {} {}", "example3", "example1"); LOG_INFO(logger, "lazy example jumps {} {} {} {} {} {} {} {} {}", std::string_view("view2"), "example1", 6LL, "example3", false, static_cast(9), "example2", std::string("str2"), 8ULL); LOG_INFO(logger, "brown logging dog fox {} {} {}", std::string_view("view2"), 3.0, 2); LOG_INFO(logger, "over test brown {} {} {} {} {} {} {} {}", std::string("str2"), 7UL, false, true, 1, 5L, std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "fox brown logging {} {} {} {} {} {} {} {}", 2, false, 6LL, 1, 4.0f, std::string_view("view1"), "example1", static_cast(9)); LOG_INFO(logger, "jumps dog quick {} {} {} {} {} {} {}", std::string("str1"), 7UL, true, 4.0f, 5L, 2, 3.0); LOG_INFO(logger, "example over lazy quick {} {} {} {} {} {} {}", 6LL, 8ULL, true, static_cast(10), 4.0f, 2, std::string("str2")); LOG_INFO(logger, "brown test quick {} {} {} {} {}", 3.0, "example1", 7UL, static_cast(9), 5L); LOG_INFO(logger, "test lazy jumps {} {} {} {} {} {} {} {} {} {}", 7UL, 1, std::string("str2"), std::string_view("view1"), "example3", "example2", static_cast(10), 6LL, 4.0f, std::string("str1")); LOG_INFO(logger, "logging over quick test {} {} {} {} {} {} {} {} {} {}", true, std::string("str1"), 5L, 6LL, 3.0, std::string_view("view2"), 8ULL, static_cast(10), false, 2); LOG_INFO(logger, "jumps brown logging {} {} {} {}", "example1", std::string("str1"), std::string_view("view1"), 7UL); LOG_INFO(logger, "test fox dog quick {} {} {} {} {} {} {} {} {}", static_cast(10), 6LL, std::string("str1"), 2, true, "example1", std::string_view("view2"), false, 3.0); LOG_INFO(logger, "fox dog logging {} {} {}", false, std::string("str1"), static_cast(10)); LOG_INFO(logger, "lazy brown logging over {} {}", 7UL, std::string("str1")); LOG_INFO(logger, "quick brown lazy over {}", "example3"); LOG_INFO(logger, "over logging test {} {} {} {} {} {}", std::string_view("view2"), static_cast(9), 2, std::string("str1"), 7UL, true); LOG_INFO(logger, "over quick dog jumps {} {} {}", static_cast(9), "example2", std::string_view("view1")); LOG_INFO(logger, "example test fox lazy {} {} {} {} {} {} {} {} {} {}", 6LL, 1, true, std::string_view("view1"), static_cast(9), std::string_view("view2"), std::string("str1"), 8ULL, "example3", false); LOG_INFO(logger, "example fox quick over {} {} {} {} {} {} {} {} {}", 7UL, static_cast(9), static_cast(10), "example2", true, 5L, 4.0f, 2, 8ULL); LOG_INFO(logger, "quick lazy test brown {} {} {} {} {} {} {} {} {}", 8ULL, 6LL, 3.0, std::string("str1"), 2, 5L, "example3", false, 1); LOG_INFO(logger, "example dog jumps lazy {}", std::string_view("view2")); LOG_INFO(logger, "fox over quick {} {} {} {} {} {} {} {} {}", 7UL, static_cast(9), std::string_view("view1"), std::string("str2"), static_cast(10), "example1", 1, 8ULL, true); LOG_INFO(logger, "over jumps brown example {} {} {} {} {} {}", std::string_view("view1"), 2, "example1", 6LL, static_cast(10), 5L); LOG_INFO(logger, "fox test over jumps {} {} {} {} {} {} {} {} {} {}", "example2", "example1", 7UL, "example3", 8ULL, std::string_view("view1"), 2, std::string("str2"), std::string("str1"), false); LOG_INFO(logger, "logging jumps lazy {} {} {} {} {}", std::string("str2"), "example3", 6LL, "example2", std::string("str1")); LOG_INFO(logger, "example jumps logging {}", 8ULL); LOG_INFO(logger, "logging test over {}", "example1"); LOG_INFO(logger, "logging lazy test {} {} {} {} {} {} {} {} {}", "example2", 1, static_cast(10), std::string_view("view2"), 3.0, static_cast(9), 7UL, 5L, 8ULL); LOG_INFO(logger, "logging dog test {} {} {}", std::string_view("view2"), 2, false); LOG_INFO(logger, "jumps example test {} {} {} {} {}", 1, true, 2, std::string("str2"), "example3"); LOG_INFO(logger, "jumps example brown {}", "example2"); LOG_INFO(logger, "logging fox quick lazy {}", static_cast(9)); LOG_INFO(logger, "logging over test jumps {} {} {} {}", std::string_view("view1"), 8ULL, std::string_view("view2"), std::string("str2")); LOG_INFO(logger, "quick test jumps {} {} {} {} {}", std::string("str2"), "example1", "example2", 8ULL, 1); LOG_INFO(logger, "test lazy dog brown {} {} {}", 2, static_cast(9), 8ULL); LOG_INFO(logger, "test quick over {} {}", std::string("str2"), "example1"); LOG_INFO(logger, "quick dog fox {} {} {}", 5L, 8ULL, "example3"); LOG_INFO(logger, "test lazy fox {} {}", std::string("str1"), std::string("str2")); LOG_INFO(logger, "example brown dog {} {} {} {} {} {} {} {} {} {}", 4.0f, std::string("str2"), "example1", 1, 5L, "example2", std::string_view("view2"), static_cast(9), std::string("str1"), 7UL); LOG_INFO(logger, "brown test example dog {} {} {} {} {}", "example3", false, std::string_view("view2"), std::string_view("view1"), 3.0); LOG_INFO(logger, "dog over lazy quick {} {} {} {} {} {} {} {} {} {}", 2, 6LL, static_cast(9), std::string_view("view2"), std::string_view("view1"), std::string("str1"), true, "example2", false, static_cast(10)); LOG_INFO(logger, "brown lazy example {} {} {}", static_cast(9), true, 7UL); LOG_INFO(logger, "jumps quick dog {} {}", std::string("str1"), 3.0); LOG_INFO(logger, "brown test over quick {} {} {} {} {} {} {}", 3.0, true, std::string("str2"), std::string_view("view2"), 7UL, static_cast(9), "example1"); LOG_INFO(logger, "brown over example logging {} {} {} {} {}", 7UL, true, "example1", std::string_view("view2"), 8ULL); LOG_INFO(logger, "quick example test brown {} {} {} {} {} {} {} {} {} {}", std::string("str1"), std::string_view("view2"), 2, 5L, "example1", 1, 6LL, 8ULL, "example3", 7UL); LOG_INFO(logger, "lazy over logging {} {} {} {} {} {} {} {} {}", static_cast(10), 1, 7UL, std::string_view("view1"), "example3", 8ULL, static_cast(9), "example2", 3.0); LOG_INFO(logger, "test quick lazy {} {} {} {} {} {}", false, "example3", 6LL, 5L, "example1", std::string_view("view2")); LOG_INFO(logger, "dog logging fox {} {} {}", 4.0f, std::string("str1"), 2); LOG_INFO(logger, "lazy logging example jumps {} {} {}", static_cast(10), std::string("str1"), 3.0); LOG_INFO(logger, "dog jumps test {} {} {} {} {} {}", "example2", std::string("str1"), 4.0f, static_cast(9), "example1", std::string_view("view1")); LOG_INFO(logger, "example jumps logging over {} {} {} {}", 7UL, "example1", std::string("str2"), "example2"); LOG_INFO(logger, "quick fox lazy {} {} {} {} {} {} {}", 1, 6LL, 3.0, 5L, static_cast(10), 2, std::string("str2")); LOG_INFO(logger, "quick jumps test {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, 6LL, "example2", 7UL, true, std::string_view("view2"), static_cast(9), false); LOG_INFO(logger, "jumps example quick lazy {} {}", false, std::string("str2")); LOG_INFO(logger, "test brown quick {} {} {}", std::string("str2"), std::string("str1"), 4.0f); LOG_INFO(logger, "lazy brown dog {} {} {} {} {} {}", std::string("str1"), 8ULL, "example2", 2, 7UL, false); LOG_INFO(logger, "fox over dog lazy {} {} {}", 5L, 3.0, std::string("str1")); LOG_INFO(logger, "over test quick jumps {} {} {} {} {} {}", std::string_view("view1"), "example3", std::string("str2"), 8ULL, std::string("str1"), std::string_view("view2")); LOG_INFO(logger, "quick test dog {} {} {} {} {} {} {} {} {} {}", 1, static_cast(10), "example3", false, true, static_cast(9), 6LL, std::string_view("view1"), "example1", 2); LOG_INFO(logger, "over brown test jumps {} {} {} {} {} {} {} {}", std::string_view("view2"), 7UL, std::string("str1"), static_cast(10), 4.0f, std::string_view("view1"), false, true); LOG_INFO(logger, "test lazy jumps over {} {}", 1, static_cast(10)); LOG_INFO(logger, "brown dog lazy {} {} {} {}", std::string_view("view1"), static_cast(10), 7UL, true); LOG_INFO(logger, "logging example dog over {}", std::string("str1")); LOG_INFO(logger, "fox brown lazy logging {} {} {} {} {} {} {} {} {} {}", 2, 6LL, 4.0f, "example3", std::string_view("view1"), "example2", true, 1, false, static_cast(10)); LOG_INFO(logger, "over brown dog lazy {} {} {} {}", 6LL, 8ULL, std::string_view("view1"), 2); LOG_INFO(logger, "lazy logging test {} {}", 2, "example1"); LOG_INFO(logger, "quick fox jumps test {} {} {} {} {} {} {}", static_cast(10), true, std::string_view("view1"), false, "example1", std::string_view("view2"), 1); LOG_INFO(logger, "jumps test dog brown {} {} {} {} {} {} {}", 1, std::string("str2"), "example3", std::string_view("view1"), static_cast(10), std::string("str1"), false); LOG_INFO(logger, "example quick logging {} {} {} {} {}", 5L, static_cast(9), false, 2, "example1"); LOG_INFO(logger, "dog example fox test {} {} {} {} {} {} {}", 3.0, "example3", std::string_view("view2"), false, 5L, 4.0f, "example2"); LOG_INFO(logger, "dog lazy jumps {} {} {} {} {} {} {} {} {} {}", static_cast(10), 3.0, "example2", "example1", 1, 6LL, 5L, 8ULL, 2, std::string_view("view2")); LOG_INFO(logger, "fox over jumps quick {} {} {} {} {}", true, 3.0, static_cast(9), std::string_view("view2"), 8ULL); LOG_INFO(logger, "lazy jumps logging {} {}", std::string_view("view2"), 1); LOG_INFO(logger, "quick logging over {} {} {} {} {} {}", 5L, std::string_view("view1"), 1, std::string_view("view2"), false, 2); LOG_INFO(logger, "logging over jumps example {}", std::string("str1")); LOG_INFO(logger, "jumps example fox {} {}", 3.0, "example1"); LOG_INFO(logger, "brown dog lazy {} {} {} {} {} {} {}", 5L, false, 7UL, "example2", std::string_view("view1"), static_cast(9), "example3"); LOG_INFO(logger, "lazy example over test {} {} {} {} {} {} {} {}", std::string("str1"), std::string_view("view2"), "example1", std::string_view("view1"), "example3", 6LL, "example2", 2); LOG_INFO(logger, "quick logging fox brown {} {} {} {} {} {} {} {} {}", 3.0, 4.0f, static_cast(9), 5L, false, 6LL, std::string("str1"), 1, std::string_view("view1")); LOG_INFO(logger, "over example quick fox {} {} {} {} {}", false, 7UL, static_cast(10), "example1", static_cast(9)); LOG_INFO(logger, "jumps dog lazy {} {} {} {}", std::string("str1"), "example3", 1, std::string_view("view1")); LOG_INFO(logger, "brown dog quick {} {} {} {} {} {} {} {}", std::string("str2"), 1, static_cast(9), "example3", static_cast(10), 3.0, std::string_view("view2"), 4.0f); LOG_INFO(logger, "jumps lazy quick {} {}", false, 1); LOG_INFO(logger, "quick logging lazy {} {} {} {} {} {} {} {} {} {}", std::string("str1"), 8ULL, 4.0f, 6LL, false, 1, static_cast(9), true, std::string_view("view2"), "example1"); LOG_INFO(logger, "brown example fox {} {} {} {}", "example2", 8ULL, 3.0, 6LL); LOG_INFO(logger, "dog over test {} {} {} {} {} {} {} {} {}", 5L, false, "example1", 1, 7UL, static_cast(10), 8ULL, static_cast(9), 4.0f); LOG_INFO(logger, "test fox logging quick {}", "example2"); LOG_INFO(logger, "lazy brown example quick {} {} {} {} {}", std::string_view("view1"), true, 5L, std::string("str1"), static_cast(10)); LOG_INFO(logger, "example dog jumps logging {} {} {} {} {} {} {} {}", 5L, 8ULL, 4.0f, static_cast(10), std::string("str2"), static_cast(9), 6LL, false); LOG_INFO(logger, "over test brown {} {} {}", 2, 4.0f, 3.0); LOG_INFO(logger, "over example brown quick {}", 5L); LOG_INFO(logger, "over example jumps lazy {} {}", std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "fox lazy over logging {} {} {} {} {} {}", 3.0, std::string_view("view1"), true, 5L, 1, std::string("str1")); LOG_INFO(logger, "test jumps example logging {} {} {} {} {} {} {} {}", "example2", 5L, 7UL, 6LL, std::string_view("view1"), "example3", "example1", std::string("str2")); LOG_INFO(logger, "brown dog fox {} {} {}", true, std::string("str1"), 5L); LOG_INFO(logger, "example brown over {} {} {} {} {}", std::string_view("view1"), "example2", 2, std::string_view("view2"), 6LL); LOG_INFO(logger, "fox dog test {} {} {} {}", static_cast(10), std::string("str1"), 8ULL, true); LOG_INFO(logger, "example quick lazy {} {}", 2, 1); LOG_INFO(logger, "jumps fox over {} {}", static_cast(9), true); LOG_INFO(logger, "dog logging over lazy {} {} {}", "example1", std::string("str1"), 4.0f); LOG_INFO(logger, "quick dog lazy example {} {} {}", 3.0, 5L, 7UL); LOG_INFO(logger, "over fox quick {} {} {} {} {} {} {} {} {}", 4.0f, static_cast(10), std::string_view("view1"), "example1", false, std::string("str1"), 6LL, 3.0, 1); LOG_INFO(logger, "lazy example logging quick {} {}", std::string("str2"), 1); LOG_INFO(logger, "jumps fox dog test {} {} {} {}", 3.0, "example2", 8ULL, 5L); LOG_INFO(logger, "quick example logging {} {} {} {} {}", std::string_view("view2"), 3.0, 8ULL, std::string("str2"), 5L); LOG_INFO(logger, "lazy example test over {} {} {} {} {} {}", 8ULL, 3.0, 1, std::string_view("view2"), std::string("str2"), "example1"); LOG_INFO(logger, "dog example jumps {} {} {} {} {} {} {} {}", static_cast(9), 7UL, 8ULL, "example1", 5L, "example3", 6LL, std::string("str1")); LOG_INFO(logger, "test jumps logging quick {} {} {}", std::string_view("view1"), 5L, false); LOG_INFO(logger, "fox jumps over {} {} {} {} {} {} {} {} {} {}", std::string("str2"), static_cast(9), std::string_view("view2"), 1, "example1", "example3", static_cast(10), 3.0, 5L, "example2"); LOG_INFO(logger, "dog logging jumps test {} {} {} {} {} {} {} {} {}", "example3", 8ULL, "example1", 6LL, std::string("str2"), static_cast(10), 2, 1, false); LOG_INFO(logger, "quick fox jumps {} {} {} {} {} {} {} {}", true, 6LL, std::string_view("view1"), 8ULL, static_cast(10), "example2", 1, 2); LOG_INFO(logger, "jumps over test logging {} {} {} {} {} {}", std::string("str2"), static_cast(9), std::string_view("view1"), "example3", "example2", std::string_view("view2")); LOG_INFO(logger, "example brown fox dog {} {} {} {} {}", 2, true, 1, 6LL, std::string("str2")); LOG_INFO(logger, "jumps dog example {} {} {} {} {} {} {} {} {}", 8ULL, 2, std::string_view("view2"), 1, std::string("str1"), "example3", "example2", static_cast(10), true); LOG_INFO(logger, "example over brown {} {} {} {} {} {} {} {} {} {}", "example3", std::string_view("view1"), 5L, 4.0f, std::string("str1"), 6LL, true, "example2", 2, 8ULL); LOG_INFO(logger, "dog brown quick example {} {} {} {} {} {} {} {} {} {}", 7UL, "example3", true, 8ULL, 1, 4.0f, false, 3.0, std::string("str1"), "example1"); LOG_INFO(logger, "jumps lazy logging {} {} {} {} {}", 6LL, 8ULL, 7UL, std::string("str1"), std::string("str2")); LOG_INFO(logger, "example quick jumps {} {} {} {} {} {} {} {}", 1, 6LL, std::string_view("view2"), "example1", std::string("str2"), std::string("str1"), 5L, false); LOG_INFO(logger, "test dog jumps over {} {} {} {} {} {} {} {} {}", "example1", std::string_view("view2"), 6LL, 8ULL, true, "example3", 2, 1, std::string("str1")); LOG_INFO(logger, "brown dog fox {} {} {} {} {} {} {} {}", 2, 5L, static_cast(9), "example1", 3.0, "example3", false, std::string("str1")); LOG_INFO(logger, "over jumps lazy {} {} {} {} {} {} {} {}", static_cast(9), 2, 1, true, 3.0, 8ULL, 4.0f, std::string_view("view1")); LOG_INFO(logger, "example brown test {} {} {} {} {} {}", 7UL, 6LL, std::string("str1"), "example2", std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "jumps brown over fox {} {}", 7UL, 1); LOG_INFO(logger, "lazy example over {} {} {} {} {} {} {} {}", true, false, 6LL, std::string_view("view1"), std::string("str2"), std::string_view("view2"), "example2", 3.0); LOG_INFO(logger, "logging example dog fox {} {} {} {}", 1, std::string_view("view1"), std::string("str2"), 4.0f); LOG_INFO(logger, "fox lazy brown quick {} {} {} {} {}", 3.0, false, std::string_view("view1"), "example2", true); LOG_INFO(logger, "test fox dog quick {} {} {} {}", "example2", "example3", 3.0, static_cast(9)); LOG_INFO(logger, "jumps dog test {} {} {} {} {}", 5L, 7UL, true, 1, std::string("str1")); LOG_INFO(logger, "quick jumps fox lazy {} {} {} {}", false, true, std::string("str1"), "example2"); LOG_INFO(logger, "jumps lazy over fox {} {} {} {} {} {} {} {} {}", std::string_view("view2"), "example1", 1, 3.0, std::string("str1"), true, "example2", "example3", static_cast(9)); LOG_INFO(logger, "brown fox lazy {} {} {} {} {} {}", true, static_cast(10), 6LL, "example3", static_cast(9), std::string_view("view1")); LOG_INFO(logger, "brown fox over {} {} {} {} {} {} {} {}", static_cast(9), std::string("str1"), std::string("str2"), 5L, 1, 6LL, std::string_view("view1"), "example1"); LOG_INFO(logger, "logging dog over brown {} {} {} {} {} {} {}", "example1", 2, "example2", std::string("str2"), 3.0, 4.0f, 8ULL); LOG_INFO(logger, "lazy fox logging {}", 7UL); LOG_INFO(logger, "quick example logging {} {} {}", false, std::string("str1"), std::string_view("view1")); LOG_INFO(logger, "quick dog test {} {} {} {}", "example3", 1, 3.0, 7UL); LOG_INFO(logger, "example lazy logging {} {} {} {} {} {} {} {}", 1, static_cast(9), "example2", static_cast(10), 3.0, 2, "example3", 8ULL); LOG_INFO(logger, "dog fox example {} {}", static_cast(10), "example1"); LOG_INFO(logger, "lazy example jumps brown {} {} {} {}", 5L, "example2", 6LL, 3.0); LOG_INFO(logger, "jumps lazy quick {} {} {} {} {} {} {} {} {}", 5L, 6LL, 8ULL, std::string("str1"), static_cast(10), std::string_view("view2"), std::string("str2"), "example3", 4.0f); LOG_INFO(logger, "over test quick {} {} {}", std::string("str1"), std::string_view("view2"), "example3"); LOG_INFO(logger, "example test brown over {} {} {} {} {} {} {} {}", static_cast(10), 8ULL, std::string_view("view1"), 6LL, static_cast(9), "example1", 5L, true); LOG_INFO(logger, "dog logging example {}", 4.0f); LOG_INFO(logger, "example jumps dog over {} {} {} {} {} {} {} {}", "example1", "example2", true, 6LL, std::string_view("view2"), 2, false, std::string("str1")); LOG_INFO(logger, "test example dog jumps {} {} {} {} {} {} {}", 1, std::string_view("view1"), 2, "example1", static_cast(9), 3.0, 6LL); LOG_INFO(logger, "jumps fox dog {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), std::string_view("view1"), "example3", 6LL, 5L, 2, true, 4.0f, 1, "example2"); LOG_INFO(logger, "fox quick over jumps {} {} {} {} {} {} {} {}", 7UL, 2, "example3", "example1", true, std::string_view("view1"), 5L, 1); LOG_INFO(logger, "test quick logging brown {} {}", true, "example2"); LOG_INFO(logger, "quick jumps logging {} {} {} {} {}", 1, 7UL, 6LL, 3.0, static_cast(10)); LOG_INFO(logger, "test logging fox quick {} {} {} {} {} {} {}", 3.0, std::string_view("view2"), std::string("str1"), 4.0f, 8ULL, false, 2); LOG_INFO(logger, "example quick logging brown {} {} {} {} {} {} {} {} {} {}", 3.0, 8ULL, std::string("str2"), 4.0f, false, true, 6LL, static_cast(10), "example1", std::string("str1")); LOG_INFO(logger, "jumps logging quick {} {}", std::string("str1"), 8ULL); LOG_INFO(logger, "fox example lazy {} {} {} {} {} {}", std::string_view("view2"), 8ULL, 6LL, 4.0f, true, "example2"); LOG_INFO(logger, "over example logging {} {} {}", std::string("str1"), "example1", "example3"); LOG_INFO(logger, "fox brown lazy over {} {} {} {} {} {} {}", 1, static_cast(9), 4.0f, std::string("str2"), 6LL, 5L, "example1"); LOG_INFO(logger, "jumps logging quick {} {} {} {} {} {} {} {} {} {}", static_cast(10), std::string_view("view1"), std::string_view("view2"), 5L, true, std::string("str2"), 4.0f, 8ULL, 3.0, "example2"); LOG_INFO(logger, "over logging example {} {} {} {} {} {} {} {} {} {}", std::string("str1"), 3.0, 2, false, 8ULL, 4.0f, 1, 6LL, std::string_view("view2"), std::string("str2")); LOG_INFO(logger, "logging brown test fox {} {} {} {}", std::string("str2"), 3.0, std::string("str1"), 1); LOG_INFO(logger, "example dog brown jumps {} {} {} {}", 1, "example2", 5L, false); LOG_INFO(logger, "logging jumps example fox {} {} {} {} {} {} {}", 3.0, std::string_view("view2"), true, static_cast(10), 5L, std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "fox brown lazy test {} {}", 2, 8ULL); LOG_INFO(logger, "dog brown lazy fox {} {} {} {} {} {} {} {}", std::string_view("view2"), 1, 4.0f, true, 7UL, "example3", 6LL, 5L); LOG_INFO(logger, "lazy test dog {}", 3.0); LOG_INFO(logger, "brown example jumps {}", 4.0f); LOG_INFO(logger, "quick logging fox jumps {} {} {} {} {} {} {} {} {} {}", 1, static_cast(9), std::string_view("view1"), std::string_view("view2"), true, 6LL, false, std::string("str1"), 2, 7UL); LOG_INFO(logger, "brown jumps test {}", 3.0); LOG_INFO(logger, "jumps lazy quick {} {} {} {} {} {} {}", 8ULL, true, std::string_view("view1"), false, std::string("str1"), "example1", std::string("str2")); LOG_INFO(logger, "example logging quick over {} {} {} {}", std::string("str1"), 1, "example1", true); LOG_INFO(logger, "example logging lazy over {} {} {} {} {} {} {} {} {}", "example2", 3.0, std::string_view("view2"), static_cast(9), "example3", 2, std::string("str1"), false, std::string_view("view1")); LOG_INFO(logger, "dog fox example quick {} {} {}", std::string("str2"), true, static_cast(9)); LOG_INFO(logger, "test quick example fox {} {} {} {} {}", true, 2, 5L, "example3", 1); LOG_INFO(logger, "quick over jumps fox {} {} {} {} {}", 6LL, 8ULL, 4.0f, true, 5L); LOG_INFO(logger, "example fox logging jumps {} {}", 6LL, 3.0); LOG_INFO(logger, "quick jumps dog {} {} {}", 6LL, std::string_view("view2"), false); LOG_INFO(logger, "lazy example quick {} {} {} {} {} {}", std::string("str2"), static_cast(9), std::string("str1"), 6LL, true, 8ULL); LOG_INFO(logger, "example logging over {} {} {} {} {}", std::string("str1"), 2, static_cast(9), std::string_view("view2"), false); LOG_INFO(logger, "test quick example {} {} {} {} {} {} {}", static_cast(10), 6LL, static_cast(9), false, std::string_view("view2"), 8ULL, "example1"); LOG_INFO(logger, "quick brown logging dog {} {} {} {} {} {} {}", 4.0f, 1, 2, std::string_view("view2"), 8ULL, static_cast(9), 7UL); LOG_INFO(logger, "logging lazy jumps {} {} {} {} {} {} {} {}", "example1", 5L, static_cast(10), std::string("str2"), true, std::string_view("view2"), 4.0f, false); LOG_INFO(logger, "over quick fox dog {} {} {} {} {} {} {} {} {}", 3.0, 1, false, 5L, 4.0f, 6LL, static_cast(9), std::string_view("view2"), std::string_view("view1")); LOG_INFO(logger, "brown fox test example {} {} {} {} {} {} {} {} {} {}", std::string("str2"), true, static_cast(10), std::string_view("view1"), 5L, "example2", false, 3.0, 1, std::string_view("view2")); LOG_INFO(logger, "example lazy jumps fox {} {} {} {} {} {}", 7UL, false, std::string_view("view1"), 6LL, "example2", 5L); LOG_INFO(logger, "fox jumps over test {} {}", "example2", "example1"); LOG_INFO(logger, "jumps dog logging {}", static_cast(10)); LOG_INFO(logger, "fox test jumps {} {} {} {} {} {} {} {}", true, std::string_view("view2"), std::string("str1"), 4.0f, 2, 6LL, std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "over quick brown {} {} {} {} {} {} {} {} {} {}", false, 8ULL, "example2", "example3", "example1", std::string("str2"), static_cast(10), 4.0f, 5L, std::string("str1")); LOG_INFO(logger, "quick brown fox example {} {} {} {} {} {}", "example1", false, static_cast(9), std::string("str1"), "example2", 4.0f); LOG_INFO(logger, "test logging jumps quick {} {} {} {} {} {}", 4.0f, true, std::string_view("view1"), "example1", 5L, 7UL); LOG_INFO(logger, "test lazy example {} {}", 2, std::string("str2")); LOG_INFO(logger, "quick over dog logging {} {} {} {} {} {} {} {} {} {}", 8ULL, std::string_view("view1"), true, 6LL, "example2", 4.0f, "example1", static_cast(10), "example3", 7UL); LOG_INFO(logger, "lazy jumps quick dog {} {} {}", std::string("str1"), "example2", false); LOG_INFO(logger, "test brown logging example {} {}", std::string_view("view2"), 6LL); LOG_INFO(logger, "over lazy dog jumps {} {} {} {} {} {}", std::string("str1"), 1, 4.0f, 6LL, 2, "example3"); LOG_INFO(logger, "lazy over fox {} {}", std::string_view("view2"), std::string_view("view1")); LOG_INFO(logger, "brown dog lazy over {} {} {} {} {} {} {} {} {} {}", "example1", "example2", 7UL, static_cast(10), 4.0f, false, 1, "example3", 2, std::string_view("view1")); LOG_INFO(logger, "jumps example over {} {} {} {}", 8ULL, static_cast(10), "example1", std::string_view("view1")); LOG_INFO(logger, "test jumps over lazy {} {} {} {}", std::string("str2"), 2, 8ULL, std::string("str1")); LOG_INFO(logger, "logging example over {} {}", std::string("str2"), static_cast(10)); LOG_INFO(logger, "jumps lazy fox {} {} {} {} {} {}", 3.0, false, 5L, static_cast(9), "example1", std::string("str2")); LOG_INFO(logger, "dog example quick brown {} {} {} {} {} {} {} {}", 5L, static_cast(9), "example3", true, false, std::string_view("view2"), 7UL, 8ULL); LOG_INFO(logger, "dog over quick {} {} {} {} {} {}", static_cast(9), static_cast(10), "example2", 5L, "example3", 2); LOG_INFO(logger, "example test jumps {} {} {} {} {} {} {} {} {}", 8ULL, false, std::string_view("view2"), true, "example3", "example1", static_cast(10), std::string_view("view1"), "example2"); LOG_INFO(logger, "example brown jumps quick {} {} {} {}", "example1", std::string("str1"), static_cast(9), 8ULL); LOG_INFO(logger, "jumps lazy dog {} {} {} {}", std::string_view("view2"), "example3", std::string("str2"), 3.0); LOG_INFO(logger, "dog lazy brown {} {}", 6LL, std::string("str1")); LOG_INFO(logger, "test quick dog {} {} {} {} {} {} {}", "example2", std::string_view("view2"), 6LL, static_cast(9), 1, std::string("str2"), 3.0); LOG_INFO(logger, "quick fox lazy over {} {} {} {} {} {} {} {}", 4.0f, false, std::string_view("view1"), 3.0, 8ULL, "example3", 6LL, "example2"); LOG_INFO(logger, "brown fox jumps {}", "example3"); LOG_INFO(logger, "logging quick fox {} {} {} {} {} {}", 1, std::string_view("view1"), std::string("str2"), 5L, false, 6LL); LOG_INFO(logger, "test dog over {}", 7UL); LOG_INFO(logger, "fox test lazy {} {} {} {} {} {} {} {} {}", 3.0, true, 6LL, std::string_view("view2"), "example2", static_cast(9), std::string_view("view1"), "example1", 4.0f); LOG_INFO(logger, "example fox quick {} {} {} {} {} {} {}", 5L, 7UL, std::string_view("view1"), "example3", "example2", "example1", static_cast(10)); LOG_INFO(logger, "dog lazy jumps {} {} {} {} {} {} {} {} {}", true, std::string_view("view1"), 7UL, 8ULL, static_cast(10), 1, 4.0f, 6LL, std::string("str2")); LOG_INFO(logger, "logging example lazy test {}", true); LOG_INFO(logger, "over quick test jumps {} {} {} {}", std::string("str2"), true, std::string("str1"), 3.0); LOG_INFO(logger, "quick example over brown {} {} {} {} {} {} {} {}", "example3", false, std::string_view("view2"), static_cast(10), 2, static_cast(9), 5L, 7UL); LOG_INFO(logger, "example test dog {} {}", 3.0, "example2"); LOG_INFO(logger, "jumps dog brown logging {} {} {} {}", std::string("str2"), std::string("str1"), "example3", "example1"); LOG_INFO(logger, "over logging lazy test {} {} {} {} {} {} {}", 6LL, true, std::string("str1"), "example2", std::string_view("view2"), 4.0f, "example1"); LOG_INFO(logger, "dog quick lazy test {} {} {} {} {} {} {} {} {}", 2, "example2", "example3", std::string("str1"), static_cast(9), 4.0f, "example1", 6LL, 5L); LOG_INFO(logger, "example test brown {} {} {}", 4.0f, "example1", 8ULL); LOG_INFO(logger, "lazy over brown jumps {} {} {} {} {} {} {}", std::string("str1"), 8ULL, 5L, 3.0, "example3", "example2", "example1"); LOG_INFO(logger, "fox quick jumps dog {} {} {} {} {} {}", 4.0f, "example1", true, std::string("str1"), std::string_view("view1"), 3.0); LOG_INFO(logger, "dog test jumps over {} {} {} {} {} {} {}", std::string_view("view1"), 4.0f, static_cast(9), 1, std::string_view("view2"), static_cast(10), false); LOG_INFO(logger, "lazy quick test {} {} {} {}", 1, static_cast(9), 3.0, std::string("str2")); LOG_INFO(logger, "jumps brown fox {} {} {} {} {} {}", std::string("str1"), static_cast(10), 8ULL, "example1", std::string("str2"), 1); LOG_INFO(logger, "test jumps quick {} {} {} {} {} {}", "example2", 1, 2, std::string_view("view2"), 8ULL, true); LOG_INFO(logger, "fox over example quick {}", std::string("str2")); LOG_INFO(logger, "over dog test {} {} {} {} {} {} {} {} {} {}", false, 3.0, "example1", std::string("str1"), std::string("str2"), 2, "example2", "example3", static_cast(9), 1); LOG_INFO(logger, "example logging dog {}", "example1"); LOG_INFO(logger, "test logging jumps {} {} {} {} {} {} {} {}", 1, "example3", std::string("str1"), 6LL, 3.0, "example1", 7UL, 5L); LOG_INFO(logger, "fox example jumps quick {} {} {} {} {} {} {} {} {} {}", 5L, std::string("str1"), false, 3.0, 2, 6LL, 7UL, true, "example3", std::string_view("view2")); LOG_INFO(logger, "fox lazy example test {} {}", true, 5L); LOG_INFO(logger, "example brown dog jumps {}", 4.0f); LOG_INFO(logger, "dog jumps fox {} {} {} {} {} {}", 8ULL, "example2", std::string_view("view2"), "example3", std::string("str2"), 3.0); LOG_INFO(logger, "quick lazy example logging {}", std::string_view("view2")); LOG_INFO(logger, "dog brown over {} {}", std::string_view("view2"), "example3"); LOG_INFO(logger, "jumps brown over {} {}", "example2", "example3"); LOG_INFO(logger, "test over quick {} {} {} {}", 4.0f, std::string("str2"), 8ULL, 5L); LOG_INFO(logger, "quick jumps brown example {} {} {} {} {} {} {}", static_cast(10), std::string("str1"), 1, 8ULL, "example2", 4.0f, static_cast(9)); LOG_INFO(logger, "over jumps dog {} {} {} {} {} {} {} {} {} {}", "example2", static_cast(10), "example1", 4.0f, std::string_view("view1"), 3.0, std::string("str2"), 5L, false, "example3"); LOG_INFO(logger, "fox jumps quick {} {} {} {} {} {} {} {}", true, 1, std::string_view("view2"), std::string_view("view1"), std::string("str1"), 5L, static_cast(10), "example1"); LOG_INFO(logger, "fox logging lazy {} {} {} {} {}", 2, 4.0f, std::string("str2"), std::string_view("view2"), 3.0); LOG_INFO(logger, "logging fox jumps {} {} {} {}", std::string_view("view2"), 4.0f, std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "fox brown dog test {} {}", 2, 7UL); LOG_INFO(logger, "lazy dog jumps brown {} {} {}", std::string_view("view2"), 3.0, "example1"); LOG_INFO(logger, "fox dog test jumps {} {} {} {}", 6LL, static_cast(9), static_cast(10), 8ULL); LOG_INFO(logger, "quick brown logging over {}", static_cast(10)); LOG_INFO(logger, "logging dog jumps {}", "example2"); LOG_INFO(logger, "quick jumps example {} {} {} {} {} {} {} {} {} {}", 8ULL, 2, static_cast(9), "example2", 6LL, std::string_view("view1"), "example3", true, 5L, 4.0f); LOG_INFO(logger, "brown over quick logging {} {} {} {} {}", false, 7UL, "example3", true, std::string_view("view1")); LOG_INFO(logger, "jumps example fox {}", 1); LOG_INFO(logger, "over example jumps quick {} {} {}", 1, 2, std::string("str1")); LOG_INFO(logger, "test over dog quick {}", "example3"); LOG_INFO(logger, "over quick logging {} {} {}", false, 4.0f, 3.0); LOG_INFO(logger, "fox test example jumps {} {} {} {} {} {} {}", static_cast(10), 8ULL, 2, "example2", std::string_view("view1"), std::string("str1"), static_cast(9)); LOG_INFO(logger, "brown jumps example logging {} {} {} {}", static_cast(9), static_cast(10), 3.0, "example3"); LOG_INFO(logger, "over fox lazy {}", 6LL); LOG_INFO(logger, "test fox example {} {} {} {} {} {} {} {}", 2, true, std::string_view("view2"), static_cast(9), std::string("str1"), 4.0f, "example1", std::string_view("view1")); LOG_INFO(logger, "dog over test {} {} {} {} {}", 5L, false, 3.0, 7UL, 8ULL); LOG_INFO(logger, "over jumps logging example {} {} {} {} {} {} {} {} {} {}", static_cast(10), "example3", std::string("str2"), true, std::string("str1"), "example1", false, 6LL, 1, "example2"); LOG_INFO(logger, "logging test fox over {} {} {} {} {} {} {} {} {}", false, true, static_cast(9), 3.0, 4.0f, 5L, 8ULL, 6LL, 1); LOG_INFO(logger, "logging lazy example {} {} {} {} {} {} {} {} {} {}", 8ULL, "example2", std::string_view("view1"), 7UL, 6LL, static_cast(10), "example3", false, 3.0, "example1"); LOG_INFO(logger, "dog brown example {}", "example1"); LOG_INFO(logger, "logging dog example fox {} {} {} {} {} {} {} {} {}", "example2", 4.0f, "example1", true, 5L, static_cast(9), 7UL, "example3", std::string_view("view1")); LOG_INFO(logger, "fox dog test {} {} {} {} {} {}", false, static_cast(10), std::string_view("view1"), static_cast(9), 7UL, "example1"); LOG_INFO(logger, "fox brown example {} {} {} {} {}", static_cast(9), "example3", 6LL, std::string("str1"), "example1"); LOG_INFO(logger, "fox dog example {}", static_cast(10)); LOG_INFO(logger, "fox quick lazy {} {} {} {} {} {} {}", std::string_view("view2"), 1, std::string("str2"), "example2", 3.0, static_cast(9), 6LL); LOG_INFO(logger, "dog test example logging {} {}", std::string_view("view1"), 8ULL); LOG_INFO(logger, "lazy quick over {}", true); LOG_INFO(logger, "over fox test {} {} {}", std::string_view("view2"), false, 1); LOG_INFO(logger, "lazy jumps over dog {}", 2); LOG_INFO(logger, "example fox brown over {} {} {} {} {}", "example1", 8ULL, "example2", 5L, 3.0); LOG_INFO(logger, "dog brown over fox {} {} {} {}", static_cast(10), "example2", 6LL, "example3"); LOG_INFO(logger, "quick lazy over {} {} {} {} {} {}", 6LL, "example3", static_cast(10), 5L, std::string_view("view1"), 7UL); LOG_INFO(logger, "over example fox quick {} {}", true, 4.0f); LOG_INFO(logger, "logging over jumps brown {} {} {} {} {} {} {} {} {} {}", "example3", 5L, std::string_view("view1"), 8ULL, static_cast(10), 7UL, std::string("str1"), 1, static_cast(9), true); LOG_INFO(logger, "lazy quick dog {} {} {} {} {} {} {}", 4.0f, "example2", "example1", 2, std::string("str1"), true, 3.0); LOG_INFO(logger, "dog example brown {} {} {} {} {} {} {}", 2, 7UL, static_cast(10), 4.0f, std::string_view("view2"), "example3", "example1"); LOG_INFO(logger, "jumps dog fox test {}", std::string_view("view2")); LOG_INFO(logger, "jumps dog quick fox {} {} {} {} {} {}", false, std::string_view("view1"), static_cast(9), 8ULL, 4.0f, 5L); LOG_INFO(logger, "fox lazy test jumps {} {} {} {} {} {} {} {} {}", 7UL, std::string("str2"), std::string_view("view1"), std::string("str1"), 4.0f, static_cast(9), "example2", 3.0, 2); LOG_INFO(logger, "test logging over fox {} {} {}", "example2", false, 8ULL); LOG_INFO(logger, "example quick brown lazy {} {} {} {} {} {} {} {}", 7UL, std::string("str2"), 5L, true, std::string_view("view1"), "example2", 2, 6LL); LOG_INFO(logger, "dog quick jumps {} {} {} {}", 5L, "example3", 1, std::string("str2")); LOG_INFO(logger, "dog fox lazy {}", false); LOG_INFO(logger, "logging fox quick {} {} {} {} {} {} {} {} {} {}", 1, std::string("str2"), 4.0f, 7UL, static_cast(10), std::string_view("view1"), static_cast(9), std::string("str1"), "example2", 5L); LOG_INFO(logger, "lazy quick example test {} {} {} {} {} {} {} {}", 5L, "example3", false, std::string_view("view2"), static_cast(10), 4.0f, "example1", 2); LOG_INFO(logger, "jumps quick dog {} {} {} {} {}", 5L, "example3", std::string("str1"), true, 7UL); LOG_INFO(logger, "example jumps logging {} {} {} {} {} {} {} {} {}", static_cast(10), 3.0, false, 2, std::string_view("view1"), "example1", std::string_view("view2"), 8ULL, 6LL); LOG_INFO(logger, "brown example test {} {} {} {} {} {}", 6LL, static_cast(10), 3.0, "example1", 4.0f, 7UL); LOG_INFO(logger, "brown jumps dog lazy {}", 2); LOG_INFO(logger, "test quick logging brown {} {} {} {} {}", 5L, "example3", 8ULL, true, 4.0f); LOG_INFO(logger, "fox logging brown {} {} {} {} {} {}", std::string_view("view1"), "example2", true, std::string("str2"), 2, 5L); LOG_INFO(logger, "test lazy quick over {} {} {} {}", 7UL, 5L, static_cast(10), std::string_view("view1")); LOG_INFO(logger, "test over brown {} {} {} {} {} {} {} {}", std::string("str2"), false, 8ULL, 2, true, "example3", 1, std::string_view("view1")); LOG_INFO(logger, "jumps brown fox logging {} {} {} {} {} {} {} {} {}", false, true, 6LL, static_cast(9), 2, 4.0f, std::string("str1"), 7UL, "example2"); LOG_INFO(logger, "logging test over {} {} {} {}", std::string("str2"), "example1", 5L, 3.0); LOG_INFO(logger, "lazy test jumps {} {} {}", 2, "example1", std::string("str2")); LOG_INFO(logger, "quick jumps fox test {} {}", 1, std::string("str2")); LOG_INFO(logger, "example logging over jumps {} {}", 7UL, 6LL); LOG_INFO(logger, "over fox test {} {} {} {} {} {} {} {} {}", 8ULL, static_cast(9), 1, std::string_view("view1"), "example1", 7UL, "example3", 3.0, 6LL); LOG_INFO(logger, "test lazy dog {} {} {}", 2, 3.0, std::string_view("view2")); LOG_INFO(logger, "quick test logging lazy {} {}", std::string_view("view2"), "example3"); LOG_INFO(logger, "quick fox test brown {} {} {} {} {} {} {} {} {}", 7UL, 1, static_cast(10), 8ULL, false, std::string_view("view2"), 3.0, "example2", std::string_view("view1")); LOG_INFO(logger, "lazy over jumps {}", std::string("str2")); LOG_INFO(logger, "test dog lazy {} {}", std::string_view("view1"), false); LOG_INFO(logger, "jumps over quick {} {} {} {} {} {} {} {}", 7UL, 1, std::string_view("view2"), "example2", 4.0f, true, static_cast(9), "example3"); LOG_INFO(logger, "logging brown jumps {} {} {} {} {} {} {} {}", std::string("str2"), false, std::string("str1"), "example3", 4.0f, 6LL, 8ULL, 5L); LOG_INFO(logger, "brown jumps quick over {} {} {} {} {}", 8ULL, 5L, "example2", static_cast(10), std::string_view("view1")); LOG_INFO(logger, "brown fox example logging {} {} {} {} {} {}", 3.0, std::string_view("view1"), 6LL, "example2", 8ULL, 7UL); LOG_INFO(logger, "dog test fox {} {} {} {} {} {}", 1, static_cast(10), static_cast(9), 2, 5L, true); LOG_INFO(logger, "dog logging quick {} {}", std::string("str2"), 7UL); LOG_INFO(logger, "jumps brown quick logging {} {} {} {} {} {}", std::string("str2"), 7UL, static_cast(10), 4.0f, 5L, false); LOG_INFO(logger, "dog logging jumps {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 2, "example1", "example3", std::string("str1"), false, static_cast(9), std::string_view("view2"), std::string_view("view1"), 5L); LOG_INFO(logger, "fox over lazy {} {} {} {} {} {}", 1, std::string_view("view2"), 3.0, "example1", std::string_view("view1"), "example3"); LOG_INFO(logger, "dog lazy quick fox {} {} {} {}", std::string_view("view2"), 4.0f, "example3", 2); LOG_INFO(logger, "fox lazy dog {} {} {} {} {} {} {} {} {} {}", "example1", 6LL, 3.0, false, "example2", std::string("str2"), std::string_view("view1"), true, 8ULL, static_cast(10)); LOG_INFO(logger, "fox over jumps {} {}", 6LL, std::string("str2")); LOG_INFO(logger, "test logging jumps {} {} {} {} {} {} {} {}", "example1", static_cast(9), 7UL, std::string("str2"), std::string_view("view2"), false, static_cast(10), 3.0); LOG_INFO(logger, "test logging lazy example {} {} {} {}", 7UL, 5L, 2, false); LOG_INFO(logger, "logging dog lazy {} {} {} {} {} {} {} {} {} {}", "example2", 2, true, "example1", static_cast(9), 4.0f, 5L, 1, "example3", 6LL); LOG_INFO(logger, "brown over fox {} {} {} {}", std::string_view("view1"), std::string_view("view2"), 8ULL, std::string("str2")); LOG_INFO(logger, "jumps logging lazy {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), 7UL, 1, 8ULL, 3.0, std::string("str1")); LOG_INFO(logger, "fox brown dog logging {}", false); LOG_INFO(logger, "brown over fox {} {} {} {} {} {} {} {} {}", 8ULL, static_cast(9), 2, 6LL, std::string_view("view1"), false, 7UL, 3.0, 1); LOG_INFO(logger, "test over dog {} {} {} {}", 5L, std::string_view("view1"), 7UL, std::string_view("view2")); LOG_INFO(logger, "dog brown jumps {} {} {}", static_cast(9), static_cast(10), 8ULL); LOG_INFO(logger, "logging brown fox over {} {} {}", false, 8ULL, std::string_view("view1")); LOG_INFO(logger, "logging over brown example {} {} {} {} {} {} {} {}", 2, 1, std::string_view("view1"), 3.0, std::string_view("view2"), static_cast(9), std::string("str1"), 5L); LOG_INFO(logger, "lazy jumps logging test {} {} {} {} {}", "example2", false, std::string("str1"), "example3", 2); LOG_INFO(logger, "brown example lazy {} {}", std::string_view("view1"), static_cast(9)); LOG_INFO(logger, "example brown quick logging {} {} {} {} {} {}", 4.0f, "example2", 3.0, 1, false, std::string("str1")); LOG_INFO(logger, "over dog test {} {} {} {} {} {} {}", 4.0f, "example1", 7UL, 5L, std::string("str2"), std::string_view("view1"), false); LOG_INFO(logger, "quick lazy jumps {} {} {} {} {} {} {} {}", 6LL, 5L, "example1", 2, "example2", 7UL, std::string_view("view1"), static_cast(9)); LOG_INFO(logger, "brown logging quick {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), std::string_view("view2"), "example3", false, 6LL, 4.0f, true, 5L); LOG_INFO(logger, "quick logging jumps {} {} {} {} {} {} {} {} {} {}", "example2", std::string_view("view2"), true, 6LL, 8ULL, static_cast(9), 4.0f, 3.0, std::string("str1"), "example1"); LOG_INFO(logger, "lazy jumps quick fox {} {}", 8ULL, std::string_view("view2")); LOG_INFO(logger, "over fox jumps {} {} {} {} {}", std::string_view("view1"), static_cast(10), static_cast(9), "example1", true); LOG_INFO(logger, "dog over lazy {} {} {} {} {}", 1, static_cast(9), std::string("str1"), true, 3.0); LOG_INFO(logger, "jumps quick fox example {} {} {} {} {} {}", std::string("str1"), 8ULL, true, false, "example3", static_cast(9)); LOG_INFO(logger, "quick lazy test brown {} {} {} {}", "example2", true, 1, "example1"); LOG_INFO(logger, "dog logging jumps {} {} {} {} {} {} {} {} {}", std::string("str1"), static_cast(9), std::string("str2"), std::string_view("view2"), 4.0f, false, "example2", static_cast(10), 1); LOG_INFO(logger, "lazy dog fox example {} {} {} {} {} {} {} {} {}", 2, "example1", static_cast(9), true, "example2", false, std::string_view("view1"), 8ULL, 4.0f); LOG_INFO(logger, "quick test lazy {} {} {} {} {} {} {} {} {}", false, std::string("str2"), 1, 2, std::string_view("view1"), 8ULL, "example2", "example3", 5L); LOG_INFO(logger, "brown lazy test over {} {} {} {} {} {} {} {} {}", static_cast(10), 5L, static_cast(9), 8ULL, 7UL, 1, 6LL, "example3", 2); LOG_INFO(logger, "dog jumps fox {} {} {} {} {} {} {} {}", 7UL, 8ULL, false, std::string("str2"), std::string_view("view2"), true, "example2", std::string("str1")); LOG_INFO(logger, "lazy jumps over {} {} {} {} {} {} {}", "example1", std::string_view("view1"), 5L, static_cast(10), 2, std::string("str1"), true); LOG_INFO(logger, "dog brown test {} {} {} {} {} {} {} {} {}", 2, std::string("str2"), std::string_view("view2"), 6LL, static_cast(9), std::string("str1"), "example3", 5L, true); LOG_INFO(logger, "test jumps logging brown {} {} {} {} {} {} {} {}", "example2", 3.0, 6LL, true, 5L, 2, 4.0f, static_cast(10)); LOG_INFO(logger, "brown lazy logging {} {} {} {} {} {}", "example3", 2, false, true, 4.0f, "example2"); LOG_INFO(logger, "logging example lazy brown {} {}", 5L, std::string("str1")); LOG_INFO(logger, "jumps example lazy logging {}", 8ULL); LOG_INFO(logger, "logging test brown {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 6LL, "example1", 8ULL, 1, 3.0, std::string_view("view1"), std::string_view("view2"), "example3", static_cast(10)); LOG_INFO(logger, "example lazy jumps {} {} {}", "example1", static_cast(10), static_cast(9)); LOG_INFO(logger, "dog test fox logging {} {} {} {} {} {}", 6LL, std::string_view("view1"), true, 5L, 8ULL, 7UL); LOG_INFO(logger, "brown over fox dog {} {} {} {} {} {} {}", 6LL, "example3", 4.0f, "example1", 3.0, true, 1); LOG_INFO(logger, "dog logging brown {} {} {} {} {} {} {} {} {}", 3.0, true, std::string("str1"), static_cast(9), 1, 2, 6LL, 5L, "example2"); LOG_INFO(logger, "logging fox dog lazy {} {} {} {} {} {}", 3.0, static_cast(9), std::string_view("view1"), "example1", 5L, 1); LOG_INFO(logger, "fox lazy dog brown {} {} {} {} {} {} {} {}", false, 1, 8ULL, 3.0, static_cast(10), true, "example2", 4.0f); LOG_INFO(logger, "quick test dog brown {} {} {}", true, std::string("str2"), static_cast(10)); LOG_INFO(logger, "jumps logging brown {} {} {} {} {} {}", false, 4.0f, std::string_view("view1"), std::string("str1"), 5L, "example1"); LOG_INFO(logger, "dog fox brown jumps {} {} {} {} {} {} {} {}", std::string_view("view2"), 5L, static_cast(9), std::string("str1"), 8ULL, 4.0f, std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "lazy over fox logging {} {} {} {} {} {}", std::string_view("view2"), 5L, 1, 4.0f, 8ULL, true); LOG_INFO(logger, "over quick example {} {} {} {} {} {} {}", static_cast(10), 1, "example1", 7UL, "example2", true, 5L); LOG_INFO(logger, "dog example over {} {} {} {}", 5L, 3.0, 7UL, 1); LOG_INFO(logger, "dog example fox {} {} {} {}", "example1", 3.0, static_cast(10), 1); LOG_INFO(logger, "quick fox dog {}", 2); LOG_INFO(logger, "fox logging example {} {} {} {}", std::string("str1"), "example1", true, false); LOG_INFO(logger, "brown fox example {} {} {} {} {} {} {}", static_cast(9), 7UL, "example3", 8ULL, 6LL, false, std::string_view("view1")); LOG_INFO(logger, "jumps logging dog {} {} {}", std::string("str2"), std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "logging lazy dog {} {} {} {} {}", 6LL, 5L, static_cast(10), std::string("str1"), "example2"); LOG_INFO(logger, "test fox logging {}", 7UL); LOG_INFO(logger, "logging lazy quick {} {}", 2, static_cast(9)); LOG_INFO(logger, "brown over example test {} {} {} {} {} {} {} {} {}", std::string("str2"), 6LL, "example1", 4.0f, std::string("str1"), false, 1, 3.0, 2); LOG_INFO(logger, "brown over example {} {} {} {} {} {} {} {} {} {}", 1, 5L, std::string_view("view1"), std::string("str1"), static_cast(9), 3.0, "example2", static_cast(10), "example1", 4.0f); LOG_INFO(logger, "test quick fox lazy {} {} {} {} {} {} {}", false, static_cast(10), std::string("str2"), 3.0, 2, true, 1); LOG_INFO(logger, "brown logging dog example {} {} {} {} {} {}", 8ULL, 5L, std::string_view("view1"), 4.0f, static_cast(9), std::string("str2")); LOG_INFO(logger, "logging brown dog {} {} {} {} {} {}", std::string("str1"), std::string_view("view1"), std::string_view("view2"), "example3", true, 2); LOG_INFO(logger, "quick fox lazy {}", 8ULL); LOG_INFO(logger, "test logging example brown {} {} {} {} {}", "example2", false, static_cast(10), 2, true); LOG_INFO(logger, "brown jumps fox {} {} {} {} {} {} {} {} {} {}", 4.0f, 8ULL, 2, std::string_view("view2"), std::string("str2"), 1, "example2", "example3", std::string("str1"), 3.0); LOG_INFO(logger, "over dog quick {} {} {} {} {} {} {} {}", std::string("str1"), 5L, true, static_cast(10), 7UL, std::string("str2"), std::string_view("view1"), 4.0f); LOG_INFO(logger, "test dog brown lazy {} {} {} {} {} {} {} {}", true, std::string_view("view2"), 6LL, std::string_view("view1"), false, 8ULL, "example3", 3.0); LOG_INFO(logger, "example fox lazy {} {}", 5L, static_cast(10)); LOG_INFO(logger, "example logging over {} {} {} {} {} {} {} {}", 8ULL, 2, 6LL, "example2", "example1", std::string("str2"), 5L, 7UL); LOG_INFO(logger, "jumps test example {} {}", 1, 7UL); LOG_INFO(logger, "over dog test example {} {} {} {} {} {} {} {} {}", static_cast(10), 2, "example3", std::string_view("view2"), 8ULL, 5L, 3.0, static_cast(9), 6LL); LOG_INFO(logger, "quick dog brown {} {} {} {} {} {} {} {} {}", static_cast(9), 4.0f, std::string("str1"), true, 6LL, 7UL, 8ULL, "example1", std::string("str2")); LOG_INFO(logger, "logging dog fox brown {} {} {} {}", std::string("str1"), 3.0, "example3", 6LL); LOG_INFO(logger, "quick test over {} {} {} {} {} {} {}", 6LL, 8ULL, std::string_view("view1"), 1, std::string_view("view2"), 7UL, true); LOG_INFO(logger, "test over fox {} {} {} {}", 5L, static_cast(9), 8ULL, 7UL); LOG_INFO(logger, "fox logging test {} {} {}", 1, 7UL, std::string_view("view1")); LOG_INFO(logger, "fox over quick {} {} {} {} {} {} {} {}", "example2", std::string_view("view2"), static_cast(9), false, 7UL, "example3", "example1", 4.0f); LOG_INFO(logger, "fox quick test example {}", std::string("str2")); LOG_INFO(logger, "quick over dog {}", "example2"); LOG_INFO(logger, "example quick fox {} {} {} {}", 7UL, std::string("str1"), "example3", 4.0f); LOG_INFO(logger, "example fox brown dog {} {} {} {} {} {} {} {} {}", 5L, static_cast(9), 3.0, "example1", 1, true, 7UL, false, std::string("str2")); LOG_INFO(logger, "lazy dog jumps quick {} {} {} {} {}", std::string_view("view1"), 1, static_cast(9), false, 6LL); LOG_INFO(logger, "logging dog test {}", 6LL); LOG_INFO(logger, "fox jumps quick logging {} {} {} {} {} {} {} {} {} {}", true, 8ULL, 1, 5L, "example1", std::string("str1"), 6LL, static_cast(10), 2, "example3"); LOG_INFO(logger, "jumps over example {} {} {} {} {} {} {} {} {} {}", static_cast(10), std::string_view("view1"), std::string_view("view2"), 8ULL, 4.0f, 3.0, std::string("str1"), true, 1, "example1"); LOG_INFO(logger, "over jumps logging {} {} {} {} {} {} {} {} {} {}", 4.0f, 5L, false, std::string_view("view1"), static_cast(9), 2, 7UL, 6LL, "example2", std::string_view("view2")); LOG_INFO(logger, "quick example jumps {}", 5L); LOG_INFO(logger, "logging brown lazy {} {} {} {} {} {} {}", std::string_view("view1"), false, static_cast(10), true, "example3", std::string("str2"), 3.0); LOG_INFO(logger, "lazy dog quick brown {} {} {} {} {} {} {} {} {} {}", 2, "example3", 7UL, 3.0, std::string("str1"), std::string_view("view2"), true, 6LL, std::string_view("view1"), false); LOG_INFO(logger, "fox logging example test {}", 1); LOG_INFO(logger, "test quick brown fox {} {} {} {} {} {}", "example1", static_cast(9), 4.0f, 1, 5L, std::string_view("view1")); LOG_INFO(logger, "dog logging test {} {} {} {}", std::string("str1"), "example1", true, std::string_view("view1")); LOG_INFO(logger, "test lazy quick example {} {} {} {} {}", 8ULL, std::string("str1"), 4.0f, 2, std::string_view("view1")); LOG_INFO(logger, "brown logging jumps dog {} {}", false, 8ULL); LOG_INFO(logger, "test lazy logging example {} {} {} {} {} {} {} {}", std::string("str2"), false, "example2", 7UL, "example3", 4.0f, std::string_view("view1"), static_cast(9)); LOG_INFO(logger, "lazy example jumps brown {} {} {}", 6LL, std::string_view("view2"), std::string("str1")); LOG_INFO(logger, "brown fox test over {} {} {} {} {} {} {} {} {} {}", static_cast(10), 1, false, 6LL, static_cast(9), 7UL, std::string_view("view2"), "example2", std::string("str2"), true); LOG_INFO(logger, "over example test {} {} {} {} {} {}", static_cast(9), 1, std::string_view("view2"), 8ULL, static_cast(10), 5L); LOG_INFO(logger, "dog fox test example {} {} {}", "example3", std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "jumps test over logging {} {} {} {} {} {} {}", 4.0f, 6LL, 5L, 2, "example1", 1, std::string_view("view2")); LOG_INFO(logger, "brown test lazy {} {} {} {} {} {} {}", false, std::string("str1"), 4.0f, "example3", std::string("str2"), 8ULL, true); LOG_INFO(logger, "example jumps brown {} {} {} {} {} {} {} {} {} {}", 2, "example3", 4.0f, 7UL, 8ULL, 3.0, static_cast(10), 1, "example1", std::string("str2")); LOG_INFO(logger, "dog fox jumps {} {}", std::string("str1"), "example2"); LOG_INFO(logger, "dog brown example {} {} {} {} {} {}", 1, std::string("str1"), 7UL, 6LL, std::string("str2"), 4.0f); LOG_INFO(logger, "jumps brown quick {} {}", static_cast(9), true); LOG_INFO(logger, "brown example jumps {} {} {}", false, 5L, std::string_view("view1")); LOG_INFO(logger, "logging quick test {} {}", std::string_view("view2"), "example3"); LOG_INFO(logger, "test over quick fox {} {} {} {} {}", 2, 5L, 3.0, true, "example2"); LOG_INFO(logger, "over lazy dog brown {} {} {} {} {}", "example2", 3.0, 2, static_cast(9), false); LOG_INFO(logger, "fox dog logging {} {} {} {} {} {}", static_cast(10), std::string_view("view2"), static_cast(9), 6LL, 5L, 1); LOG_INFO(logger, "over logging brown quick {} {} {} {} {} {} {} {} {} {}", static_cast(9), "example2", std::string_view("view1"), 8ULL, 2, std::string("str1"), static_cast(10), 7UL, 6LL, "example3"); LOG_INFO(logger, "brown logging lazy quick {} {} {} {} {} {}", 5L, static_cast(10), static_cast(9), std::string("str2"), 8ULL, true); LOG_INFO(logger, "example test quick {} {}", std::string("str1"), static_cast(10)); LOG_INFO(logger, "brown over jumps {} {} {}", true, 1, std::string_view("view1")); LOG_INFO(logger, "dog over lazy example {} {} {} {}", "example1", "example3", 2, 7UL); LOG_INFO(logger, "fox test quick {} {} {} {} {} {} {} {} {} {}", 1, "example2", 7UL, static_cast(10), 3.0, 2, 5L, std::string_view("view1"), 4.0f, 6LL); LOG_INFO(logger, "lazy test brown {} {} {}", 2, false, 5L); LOG_INFO(logger, "lazy example fox quick {} {} {} {} {} {} {}", false, 4.0f, 5L, std::string("str1"), "example3", 7UL, std::string_view("view1")); LOG_INFO(logger, "quick brown test dog {} {} {} {} {} {} {} {} {} {}", 7UL, "example2", false, 8ULL, std::string("str2"), 6LL, 2, std::string("str1"), "example1", true); LOG_INFO(logger, "quick logging test over {} {} {} {}", std::string_view("view1"), "example1", static_cast(9), 2); LOG_INFO(logger, "jumps logging dog {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), std::string("str2"), 6LL, 3.0, 2, static_cast(10), false, 8ULL, true, 4.0f); LOG_INFO(logger, "quick logging over dog {} {} {} {} {} {} {} {}", 5L, true, 3.0, "example2", 2, 7UL, "example1", std::string_view("view1")); LOG_INFO(logger, "example over lazy fox {} {} {} {}", std::string_view("view1"), 6LL, "example1", std::string_view("view2")); LOG_INFO(logger, "jumps brown quick {} {} {} {}", "example1", 3.0, 5L, std::string("str1")); LOG_INFO(logger, "lazy quick over jumps {} {} {}", 2, true, static_cast(9)); LOG_INFO(logger, "brown example dog {}", 5L); LOG_INFO(logger, "over brown logging dog {} {}", static_cast(10), 6LL); LOG_INFO(logger, "test lazy over dog {} {} {} {} {}", 6LL, static_cast(9), 3.0, false, 1); LOG_INFO(logger, "over lazy jumps brown {} {} {} {}", static_cast(9), std::string("str2"), 8ULL, 5L); LOG_INFO(logger, "lazy fox example {} {} {}", 8ULL, std::string_view("view1"), static_cast(9)); LOG_INFO(logger, "logging jumps dog test {} {} {}", static_cast(9), true, 7UL); LOG_INFO(logger, "test example over lazy {} {} {} {} {} {} {} {}", static_cast(10), 6LL, 7UL, static_cast(9), "example1", true, std::string("str1"), false); LOG_INFO(logger, "lazy over test {} {} {} {} {} {} {} {} {}", std::string("str1"), 7UL, "example2", true, std::string_view("view1"), 6LL, "example1", 4.0f, std::string("str2")); LOG_INFO(logger, "jumps example lazy {} {}", "example3", std::string_view("view2")); LOG_INFO(logger, "fox logging lazy test {} {} {} {} {} {} {} {}", static_cast(10), 5L, "example2", 4.0f, 3.0, std::string_view("view2"), 2, "example1"); LOG_INFO(logger, "fox over quick test {} {} {} {} {} {} {} {} {}", "example1", static_cast(10), static_cast(9), "example2", false, std::string_view("view2"), 6LL, "example3", 5L); LOG_INFO(logger, "test quick over logging {} {}", std::string_view("view2"), 6LL); LOG_INFO(logger, "logging test quick over {} {}", true, 6LL); LOG_INFO(logger, "lazy quick fox {} {} {} {} {} {} {} {}", 4.0f, false, 8ULL, std::string_view("view1"), 6LL, 3.0, std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "dog lazy test jumps {} {} {} {} {} {} {}", 2, 8ULL, 1, static_cast(10), "example1", true, static_cast(9)); LOG_INFO(logger, "lazy dog test fox {}", std::string("str1")); LOG_INFO(logger, "test jumps example brown {} {} {} {} {} {} {}", false, 4.0f, 2, std::string_view("view1"), "example1", 6LL, std::string("str2")); LOG_INFO(logger, "fox dog lazy logging {} {} {} {} {} {} {} {} {}", "example3", std::string("str2"), 8ULL, "example1", false, "example2", 4.0f, 3.0, std::string("str1")); LOG_INFO(logger, "fox test example brown {} {}", std::string("str1"), "example2"); LOG_INFO(logger, "test quick logging {}", std::string("str1")); LOG_INFO(logger, "brown fox example jumps {} {} {} {} {} {} {} {}", std::string_view("view1"), 7UL, false, 6LL, std::string("str1"), 8ULL, std::string_view("view2"), "example3"); LOG_INFO(logger, "lazy logging fox jumps {} {} {} {} {}", std::string_view("view1"), "example2", "example3", false, static_cast(9)); LOG_INFO(logger, "dog jumps example over {}", true); LOG_INFO(logger, "brown lazy quick {} {} {} {} {} {} {} {}", static_cast(10), std::string("str1"), true, std::string("str2"), std::string_view("view2"), 4.0f, "example3", false); LOG_INFO(logger, "dog fox jumps logging {} {} {}", 6LL, 5L, 1); LOG_INFO(logger, "jumps brown example quick {} {} {} {} {} {}", std::string_view("view1"), 7UL, "example3", 8ULL, 6LL, 3.0); LOG_INFO(logger, "quick example jumps lazy {} {} {} {} {}", static_cast(10), false, std::string_view("view1"), 1, 7UL); LOG_INFO(logger, "dog lazy quick over {}", "example3"); LOG_INFO(logger, "over dog brown {} {} {} {} {} {}", 8ULL, 7UL, std::string("str2"), "example3", 1, std::string_view("view1")); LOG_INFO(logger, "test quick dog lazy {} {} {}", "example3", "example1", "example2"); LOG_INFO(logger, "dog fox jumps over {} {}", static_cast(10), "example3"); LOG_INFO(logger, "jumps fox lazy dog {} {} {} {} {} {} {} {} {}", 5L, 2, "example3", "example2", static_cast(10), 3.0, std::string("str2"), 6LL, 8ULL); LOG_INFO(logger, "over quick fox {} {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), 4.0f, 8ULL, 2, 1, std::string("str2")); LOG_INFO(logger, "dog test lazy {} {} {} {}", 8ULL, std::string_view("view1"), "example3", 3.0); LOG_INFO(logger, "fox jumps example dog {} {}", "example2", static_cast(10)); LOG_INFO(logger, "logging lazy jumps example {} {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), std::string_view("view1"), 7UL, true, 5L, 4.0f); LOG_INFO(logger, "dog example fox {} {}", 6LL, std::string("str2")); LOG_INFO(logger, "logging dog quick {} {} {} {} {}", static_cast(9), true, false, std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "jumps example over {} {} {} {} {} {} {}", 3.0, false, std::string_view("view1"), 4.0f, std::string("str2"), 5L, std::string_view("view2")); LOG_INFO(logger, "example jumps test brown {} {} {} {} {} {}", std::string("str2"), 6LL, 7UL, static_cast(9), "example2", 8ULL); LOG_INFO(logger, "dog logging quick {} {} {} {} {} {} {}", "example1", std::string("str2"), 8ULL, "example2", "example3", static_cast(10), 3.0); LOG_INFO(logger, "quick logging brown {} {} {} {} {}", true, 3.0, static_cast(10), 5L, std::string("str1")); LOG_INFO(logger, "quick lazy dog brown {} {} {} {} {} {} {} {} {}", 7UL, static_cast(10), 3.0, 1, "example2", "example1", 6LL, false, static_cast(9)); LOG_INFO(logger, "jumps quick over {} {} {} {} {} {}", std::string("str2"), 4.0f, "example3", 1, true, "example2"); LOG_INFO(logger, "quick dog example jumps {} {} {} {} {} {} {} {}", "example1", 2, 6LL, false, static_cast(10), 5L, 1, std::string_view("view1")); LOG_INFO(logger, "jumps dog quick test {}", 2); LOG_INFO(logger, "logging fox example {} {} {} {} {} {} {} {} {}", true, 2, static_cast(10), std::string("str1"), std::string("str2"), std::string_view("view1"), "example1", 1, static_cast(9)); LOG_INFO(logger, "brown test dog {} {} {} {} {}", "example3", std::string_view("view1"), false, 6LL, std::string("str1")); LOG_INFO(logger, "over example logging brown {} {} {} {}", "example1", 1, 6LL, 7UL); LOG_INFO(logger, "logging jumps test example {} {} {}", 1, 8ULL, 6LL); LOG_INFO(logger, "logging brown lazy example {} {}", 6LL, static_cast(9)); LOG_INFO(logger, "quick jumps lazy example {} {}", 7UL, 2); LOG_INFO(logger, "brown over logging lazy {} {}", std::string("str2"), 7UL); LOG_INFO(logger, "logging brown fox {}", std::string_view("view2")); LOG_INFO(logger, "quick fox test {} {} {}", "example2", 5L, static_cast(10)); LOG_INFO(logger, "quick test over brown {} {} {}", std::string_view("view1"), true, 2); LOG_INFO(logger, "brown lazy jumps {} {} {} {} {} {} {}", 5L, "example2", 3.0, true, 4.0f, std::string("str1"), static_cast(9)); LOG_INFO(logger, "test jumps lazy logging {} {} {}", std::string_view("view2"), static_cast(9), 7UL); LOG_INFO(logger, "brown quick dog jumps {}", false); LOG_INFO(logger, "fox example test brown {} {} {} {} {} {}", 1, std::string_view("view2"), 3.0, false, 8ULL, "example1"); LOG_INFO(logger, "dog quick brown test {} {} {} {}", std::string_view("view2"), "example1", std::string_view("view1"), 5L); LOG_INFO(logger, "quick lazy example fox {} {} {} {} {} {} {} {} {} {}", 1, 2, 8ULL, false, 6LL, true, "example2", "example1", 4.0f, static_cast(9)); LOG_INFO(logger, "lazy dog brown fox {} {} {} {}", 6LL, true, std::string("str2"), 3.0); LOG_INFO(logger, "quick test brown fox {} {} {} {} {}", std::string("str2"), std::string_view("view2"), false, "example3", 5L); LOG_INFO(logger, "dog jumps brown {}", static_cast(10)); LOG_INFO(logger, "dog test example jumps {} {} {} {} {} {}", static_cast(10), true, 8ULL, std::string("str1"), std::string_view("view1"), 2); LOG_INFO(logger, "brown logging fox {} {} {} {} {} {} {} {}", "example1", static_cast(9), "example3", "example2", true, static_cast(10), std::string("str2"), 5L); LOG_INFO(logger, "lazy dog jumps {} {} {} {} {} {} {} {} {} {}", 7UL, 5L, std::string_view("view2"), std::string("str1"), true, 3.0, std::string("str2"), "example1", 8ULL, static_cast(9)); LOG_INFO(logger, "dog lazy quick {} {} {} {} {} {} {}", 8ULL, 6LL, true, 2, 1, 4.0f, "example2"); LOG_INFO(logger, "logging over brown example {} {} {} {} {} {} {} {} {}", true, 3.0, 8ULL, "example1", std::string_view("view2"), 5L, "example2", 6LL, std::string_view("view1")); LOG_INFO(logger, "logging example test {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 5L, "example3", 8ULL, 2, "example2", 7UL, std::string_view("view1"), static_cast(9), std::string("str2")); LOG_INFO(logger, "jumps over example test {} {} {} {} {} {} {} {} {}", 7UL, std::string("str2"), true, 1, "example2", "example1", static_cast(10), std::string_view("view1"), 6LL); LOG_INFO(logger, "brown lazy over {} {} {} {} {} {}", static_cast(9), "example1", "example2", 8ULL, 3.0, std::string("str1")); LOG_INFO(logger, "logging jumps test {} {}", 1, "example1"); LOG_INFO(logger, "quick brown logging {} {} {} {} {} {} {}", 1, 4.0f, 7UL, "example3", std::string_view("view2"), static_cast(9), 3.0); LOG_INFO(logger, "jumps dog over test {} {} {} {} {} {} {} {} {}", std::string_view("view2"), false, std::string_view("view1"), 7UL, "example1", "example2", static_cast(9), 4.0f, 6LL); LOG_INFO(logger, "over dog quick fox {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), "example3", std::string("str1"), "example2", 5L); LOG_INFO(logger, "quick test fox brown {} {}", 8ULL, static_cast(10)); LOG_INFO(logger, "example brown jumps quick {} {} {} {} {} {}", std::string_view("view2"), false, 1, 6LL, 8ULL, 3.0); LOG_INFO(logger, "brown example test quick {} {}", static_cast(9), 4.0f); LOG_INFO(logger, "example dog lazy {} {} {} {} {} {} {} {} {} {}", 5L, 2, std::string("str2"), static_cast(10), 1, std::string_view("view2"), false, 4.0f, 6LL, std::string_view("view1")); LOG_INFO(logger, "over logging dog {} {} {} {} {} {} {} {} {} {}", 7UL, 5L, 8ULL, 3.0, static_cast(10), "example1", std::string_view("view1"), std::string_view("view2"), true, std::string("str1")); LOG_INFO(logger, "quick test example {} {} {} {} {} {} {} {}", 8ULL, 7UL, false, "example1", "example3", std::string("str2"), 2, 6LL); LOG_INFO(logger, "brown test lazy fox {} {} {} {} {} {} {} {} {} {}", "example3", 6LL, "example2", std::string_view("view1"), 8ULL, static_cast(9), 4.0f, 3.0, 5L, false); LOG_INFO(logger, "over test fox quick {} {} {} {} {} {} {}", 3.0, 2, std::string("str2"), static_cast(9), 1, std::string_view("view1"), 8ULL); LOG_INFO(logger, "test brown jumps {} {} {} {} {} {} {} {}", 7UL, "example2", std::string("str1"), true, 6LL, false, 8ULL, "example3"); LOG_INFO(logger, "over brown quick {} {} {} {} {} {} {} {}", 2, 7UL, "example1", static_cast(10), std::string_view("view2"), std::string("str1"), 1, 3.0); LOG_INFO(logger, "quick jumps over logging {} {} {} {} {} {} {} {} {}", 5L, false, 3.0, std::string("str1"), "example1", 7UL, static_cast(10), std::string("str2"), static_cast(9)); LOG_INFO(logger, "dog over jumps {} {} {} {} {} {} {} {}", "example2", "example3", 6LL, false, std::string_view("view1"), 2, 3.0, "example1"); LOG_INFO(logger, "lazy quick test logging {} {} {}", false, std::string_view("view1"), 8ULL); LOG_INFO(logger, "fox quick over {} {} {} {} {} {} {} {} {} {}", "example1", 6LL, 4.0f, std::string_view("view1"), false, 1, 3.0, 7UL, std::string_view("view2"), 5L); LOG_INFO(logger, "jumps lazy over logging {} {} {} {} {} {} {} {} {}", std::string("str1"), "example1", 3.0, "example2", "example3", true, 4.0f, std::string_view("view1"), 6LL); LOG_INFO(logger, "fox example quick {} {} {} {} {} {} {} {} {} {}", static_cast(9), "example3", false, 5L, 7UL, 3.0, 8ULL, std::string_view("view1"), static_cast(10), 4.0f); LOG_INFO(logger, "jumps over dog brown {} {} {}", 3.0, 8ULL, "example1"); LOG_INFO(logger, "jumps quick test {} {} {} {} {} {} {} {}", 7UL, 4.0f, "example2", std::string("str2"), 3.0, false, 8ULL, 5L); LOG_INFO(logger, "brown logging over fox {} {}", 5L, 6LL); LOG_INFO(logger, "jumps dog over quick {} {} {} {} {} {} {}", static_cast(10), std::string("str1"), "example2", "example1", std::string_view("view2"), "example3", 1); LOG_INFO(logger, "over quick brown {} {} {} {} {} {} {} {}", 8ULL, 6LL, std::string("str2"), true, "example2", 1, std::string_view("view2"), std::string_view("view1")); LOG_INFO(logger, "logging quick brown fox {} {} {} {} {} {} {}", std::string_view("view1"), 1, false, std::string("str1"), 6LL, "example2", std::string_view("view2")); LOG_INFO(logger, "jumps fox logging {} {}", static_cast(10), static_cast(9)); LOG_INFO(logger, "fox example dog {} {} {} {}", static_cast(10), std::string("str2"), true, "example3"); LOG_INFO(logger, "brown quick logging fox {} {} {} {} {} {} {} {} {}", 8ULL, 5L, static_cast(9), "example1", 6LL, std::string("str1"), std::string_view("view2"), "example2", true); LOG_INFO(logger, "lazy dog test {} {} {} {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), std::string_view("view1"), false, 8ULL, "example3", 3.0, 2, std::string("str1")); LOG_INFO(logger, "lazy test example over {}", "example1"); LOG_INFO(logger, "test brown fox example {} {} {} {} {} {} {} {} {} {}", 3.0, true, std::string("str2"), 8ULL, 1, "example1", false, static_cast(9), "example3", "example2"); LOG_INFO(logger, "example lazy jumps {} {} {} {} {} {} {} {} {} {}", 2, 5L, "example2", 4.0f, static_cast(9), 6LL, static_cast(10), true, 1, 7UL); LOG_INFO(logger, "fox test jumps {} {} {} {} {} {} {} {} {}", std::string("str1"), "example2", 4.0f, std::string_view("view1"), 6LL, 1, static_cast(9), 5L, std::string_view("view2")); LOG_INFO(logger, "brown lazy example {} {} {} {} {} {} {} {} {}", "example2", std::string_view("view1"), "example1", true, static_cast(9), 5L, 2, 1, 8ULL); LOG_INFO(logger, "fox brown dog test {} {} {}", std::string_view("view2"), false, 4.0f); LOG_INFO(logger, "example test brown {} {} {} {}", 6LL, 8ULL, true, 1); LOG_INFO(logger, "over example logging brown {} {}", 5L, std::string("str1")); LOG_INFO(logger, "example dog test {} {} {} {} {} {}", false, "example2", 4.0f, std::string("str1"), "example3", 2); LOG_INFO(logger, "over quick logging {} {} {}", 1, std::string_view("view2"), 8ULL); LOG_INFO(logger, "logging jumps example {} {} {} {} {} {} {} {}", 7UL, std::string("str2"), 6LL, "example2", 5L, 8ULL, false, std::string("str1")); LOG_INFO(logger, "jumps dog quick {} {}", 8ULL, 5L); LOG_INFO(logger, "logging fox test {} {} {} {}", 7UL, false, 2, std::string_view("view2")); LOG_INFO(logger, "fox over dog quick {} {} {} {} {} {} {} {}", 7UL, "example1", std::string_view("view1"), true, 2, 4.0f, 6LL, false); LOG_INFO(logger, "test jumps quick {} {} {} {} {} {} {}", 2, false, "example1", 8ULL, 6LL, static_cast(10), 4.0f); LOG_INFO(logger, "jumps logging dog fox {}", std::string_view("view1")); LOG_INFO(logger, "fox lazy test {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, "example1", true, std::string("str2"), 5L, 4.0f, static_cast(10)); LOG_INFO(logger, "fox brown jumps {} {} {} {} {} {} {}", std::string("str1"), 7UL, static_cast(9), std::string_view("view1"), false, 1, "example3"); LOG_INFO(logger, "over example fox {} {} {} {}", std::string_view("view1"), "example1", 8ULL, std::string_view("view2")); LOG_INFO(logger, "example lazy quick {} {} {} {} {} {} {}", 8ULL, 2, static_cast(10), 3.0, std::string("str2"), 4.0f, 7UL); LOG_INFO(logger, "logging fox brown jumps {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 8ULL, std::string("str2"), true, std::string_view("view2"), 7UL, 3.0, false, "example2"); LOG_INFO(logger, "over brown quick {} {}", true, 1); LOG_INFO(logger, "brown dog jumps {} {} {}", false, 8ULL, 2); LOG_INFO(logger, "dog brown quick lazy {} {} {} {} {}", "example3", "example1", 8ULL, 3.0, "example2"); LOG_INFO(logger, "fox quick brown over {} {} {} {} {} {} {} {} {}", std::string_view("view2"), "example2", 2, 8ULL, "example1", std::string("str1"), 4.0f, false, 3.0); LOG_INFO(logger, "over fox lazy {} {} {} {} {} {}", 5L, 4.0f, std::string("str1"), 8ULL, std::string_view("view2"), 3.0); LOG_INFO(logger, "lazy dog test {} {} {} {} {} {} {} {}", 2, "example2", false, 6LL, std::string("str1"), 8ULL, static_cast(9), 1); LOG_INFO(logger, "lazy quick brown logging {} {}", 1, 4.0f); LOG_INFO(logger, "over quick fox {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), 2, std::string("str2"), std::string("str1"), 3.0); LOG_INFO(logger, "test dog jumps lazy {} {} {}", 6LL, "example2", 7UL); LOG_INFO(logger, "lazy dog jumps over {}", 7UL); LOG_INFO(logger, "logging jumps fox lazy {} {} {}", false, 6LL, 4.0f); LOG_INFO(logger, "jumps fox example {} {}", "example2", std::string_view("view2")); LOG_INFO(logger, "quick jumps test dog {} {} {} {} {} {}", 7UL, 8ULL, 1, 6LL, 4.0f, std::string_view("view1")); LOG_INFO(logger, "brown example dog {} {} {} {} {} {}", 4.0f, false, std::string("str1"), static_cast(9), 6LL, true); LOG_INFO(logger, "brown logging example {} {} {} {}", static_cast(10), 7UL, false, 3.0); LOG_INFO(logger, "quick fox test {} {} {} {} {} {}", 3.0, std::string_view("view2"), true, false, std::string("str1"), std::string("str2")); LOG_INFO(logger, "lazy quick over {} {} {} {} {} {} {}", 6LL, false, static_cast(9), true, 7UL, 5L, std::string_view("view2")); LOG_INFO(logger, "jumps lazy over {} {}", "example3", 2); LOG_INFO(logger, "test dog jumps logging {} {} {} {} {} {} {} {} {} {}", false, 8ULL, static_cast(9), 7UL, std::string_view("view2"), "example1", 1, 5L, "example3", 2); LOG_INFO(logger, "brown logging quick example {} {} {} {} {} {} {} {}", 2, "example3", static_cast(10), std::string_view("view1"), true, std::string("str2"), false, 5L); LOG_INFO(logger, "over dog jumps quick {} {} {}", 3.0, 4.0f, 8ULL); LOG_INFO(logger, "fox lazy test quick {} {} {} {} {} {} {} {}", 5L, 4.0f, "example2", std::string("str2"), 6LL, static_cast(10), 7UL, std::string_view("view1")); LOG_INFO(logger, "jumps over logging lazy {} {} {} {} {} {} {} {} {} {}", static_cast(10), 6LL, 7UL, 1, 5L, 4.0f, std::string_view("view2"), false, "example1", 3.0); LOG_INFO(logger, "lazy over test {} {}", std::string("str1"), 3.0); LOG_INFO(logger, "fox brown over {} {} {} {} {} {} {} {}", 6LL, std::string("str1"), static_cast(9), 2, "example1", 5L, false, std::string_view("view2")); LOG_INFO(logger, "brown lazy fox {}", static_cast(9)); LOG_INFO(logger, "fox dog brown {} {} {} {} {}", true, 8ULL, std::string_view("view2"), std::string("str1"), 6LL); LOG_INFO(logger, "dog example over {} {} {} {}", static_cast(10), 6LL, 1, 3.0); LOG_INFO(logger, "jumps dog brown {} {} {} {} {} {} {} {}", std::string_view("view1"), static_cast(9), true, std::string("str2"), 8ULL, 2, 4.0f, "example3"); LOG_INFO(logger, "jumps test logging {} {}", "example3", std::string_view("view1")); LOG_INFO(logger, "example dog logging over {} {} {} {} {} {} {} {} {} {}", 2, static_cast(9), 5L, "example1", 6LL, true, std::string("str2"), 4.0f, 8ULL, 1); LOG_INFO(logger, "dog logging lazy example {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 1, 5L, 3.0, std::string("str1"), static_cast(10), std::string_view("view1"), 6LL, 7UL, static_cast(9)); LOG_INFO(logger, "jumps logging fox brown {} {} {} {} {} {}", false, 4.0f, std::string("str1"), std::string_view("view1"), "example2", 3.0); LOG_INFO(logger, "fox brown example {} {} {} {} {}", 1, 5L, "example2", static_cast(10), std::string("str1")); LOG_INFO(logger, "test fox example brown {} {} {} {} {} {} {} {} {} {}", std::string("str1"), "example2", 7UL, 2, 8ULL, std::string_view("view1"), static_cast(10), true, false, 4.0f); LOG_INFO(logger, "lazy brown jumps {} {} {} {} {} {} {} {} {} {}", 2, std::string("str1"), std::string("str2"), 4.0f, 1, "example3", static_cast(10), true, false, "example1"); LOG_INFO(logger, "quick jumps test lazy {} {} {} {} {}", 1, static_cast(9), 7UL, std::string("str1"), 4.0f); LOG_INFO(logger, "example jumps over lazy {} {} {} {} {} {} {}", 8ULL, true, std::string_view("view2"), 4.0f, static_cast(9), std::string_view("view1"), 6LL); LOG_INFO(logger, "brown fox dog logging {} {} {} {} {} {} {} {} {} {}", 2, std::string("str2"), "example1", 4.0f, 5L, false, 7UL, 1, 6LL, 8ULL); LOG_INFO(logger, "lazy quick fox over {} {}", std::string_view("view2"), 4.0f); LOG_INFO(logger, "jumps over example dog {} {}", std::string_view("view2"), static_cast(9)); LOG_INFO(logger, "brown example over {} {}", std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "test example fox logging {} {} {} {}", 4.0f, std::string("str1"), "example1", "example3"); LOG_INFO(logger, "fox over lazy test {} {} {}", "example1", 3.0, static_cast(9)); LOG_INFO(logger, "example dog lazy {} {} {} {} {}", "example1", 6LL, 7UL, 4.0f, 5L); LOG_INFO(logger, "lazy logging over {} {} {} {} {} {} {} {} {}", false, static_cast(9), static_cast(10), 8ULL, std::string("str2"), 2, 5L, "example1", std::string("str1")); LOG_INFO(logger, "test quick jumps {} {} {} {} {}", true, "example2", std::string_view("view1"), std::string("str1"), "example3"); LOG_INFO(logger, "test brown dog {} {} {} {} {}", 8ULL, 2, 6LL, static_cast(10), "example1"); LOG_INFO(logger, "logging test brown {} {} {} {} {} {} {} {}", 1, "example2", static_cast(10), std::string("str2"), 3.0, 6LL, static_cast(9), std::string("str1")); LOG_INFO(logger, "test jumps lazy {} {} {} {} {} {} {}", 4.0f, "example1", 6LL, "example2", 2, 3.0, 8ULL); LOG_INFO(logger, "brown over dog {} {} {} {} {} {} {} {} {}", 1, 6LL, 3.0, std::string("str1"), std::string_view("view2"), 5L, static_cast(10), false, static_cast(9)); LOG_INFO(logger, "logging brown over example {} {} {} {} {} {} {} {} {}", "example3", 3.0, true, false, std::string_view("view1"), 7UL, 6LL, std::string("str2"), "example2"); LOG_INFO(logger, "jumps test quick {} {} {} {} {} {} {}", false, 4.0f, static_cast(9), std::string_view("view2"), "example3", 3.0, std::string("str2")); LOG_INFO(logger, "dog jumps test example {} {} {} {} {} {}", 5L, static_cast(10), 4.0f, 8ULL, std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "brown over lazy example {} {} {} {} {} {} {} {}", std::string("str1"), "example3", std::string_view("view1"), 5L, std::string_view("view2"), "example2", 2, true); LOG_INFO(logger, "lazy dog test {} {} {}", true, 1, 2); LOG_INFO(logger, "fox brown example {} {} {}", std::string("str1"), static_cast(10), 2); LOG_INFO(logger, "example dog quick brown {} {} {} {} {} {} {} {}", 8ULL, 4.0f, 7UL, true, std::string("str2"), std::string("str1"), std::string_view("view2"), 2); LOG_INFO(logger, "example dog quick {}", true); LOG_INFO(logger, "test dog quick {} {} {} {} {}", std::string_view("view2"), 5L, 8ULL, 7UL, 6LL); LOG_INFO(logger, "brown lazy jumps {} {} {} {} {} {} {}", 1, 2, 3.0, std::string("str1"), "example1", std::string_view("view1"), true); LOG_INFO(logger, "fox over dog {} {} {} {} {} {} {} {}", "example3", std::string_view("view2"), 1, true, "example1", std::string("str2"), "example2", static_cast(10)); LOG_INFO(logger, "over brown quick {} {} {}", false, 8ULL, 4.0f); LOG_INFO(logger, "quick example jumps fox {}", 6LL); LOG_INFO(logger, "logging jumps quick {} {}", std::string("str2"), "example1"); LOG_INFO(logger, "dog logging lazy {} {} {} {}", std::string_view("view2"), true, std::string("str1"), 8ULL); LOG_INFO(logger, "example fox jumps dog {} {} {} {} {} {}", true, 3.0, 1, 7UL, "example3", false); LOG_INFO(logger, "test example lazy {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, 1, 4.0f, 2, static_cast(10), std::string("str1"), true, "example1"); LOG_INFO(logger, "logging dog test example {} {} {} {} {}", "example2", 4.0f, 8ULL, true, std::string_view("view1")); LOG_INFO(logger, "lazy example quick {} {} {} {} {} {} {} {} {} {}", false, 8ULL, 3.0, 6LL, "example1", true, std::string_view("view1"), static_cast(10), "example3", std::string("str1")); LOG_INFO(logger, "fox quick lazy {} {} {}", 7UL, 3.0, 1); LOG_INFO(logger, "brown quick fox test {} {} {} {} {} {} {}", std::string_view("view2"), 1, 6LL, 5L, std::string("str2"), static_cast(10), true); LOG_INFO(logger, "fox test logging {} {} {} {} {} {} {} {} {} {}", 5L, 1, 8ULL, std::string("str1"), "example3", std::string_view("view1"), 4.0f, std::string("str2"), "example2", false); LOG_INFO(logger, "brown fox jumps over {} {} {} {} {} {} {}", std::string("str1"), 5L, 3.0, std::string_view("view2"), static_cast(10), false, std::string_view("view1")); LOG_INFO(logger, "test lazy example {} {} {} {}", 6LL, 1, 5L, "example1"); LOG_INFO(logger, "over dog brown {} {} {}", std::string("str2"), 4.0f, static_cast(9)); LOG_INFO(logger, "example brown test {} {} {}", 4.0f, true, 3.0); LOG_INFO(logger, "lazy test logging fox {} {}", 5L, 3.0); LOG_INFO(logger, "example fox lazy quick {} {} {} {} {} {} {} {}", 6LL, 7UL, true, static_cast(10), 3.0, std::string("str2"), "example1", std::string_view("view2")); LOG_INFO(logger, "brown over test fox {} {} {} {} {} {} {} {} {}", 6LL, "example2", 3.0, 4.0f, 1, std::string_view("view1"), std::string("str2"), false, true); LOG_INFO(logger, "lazy over example {}", 4.0f); LOG_INFO(logger, "lazy example fox {} {} {} {} {} {} {} {} {}", "example2", "example3", 3.0, 8ULL, 1, std::string("str1"), 7UL, std::string_view("view2"), std::string("str2")); LOG_INFO(logger, "brown test lazy quick {} {} {} {} {} {} {} {}", std::string("str2"), static_cast(9), "example3", "example1", 8ULL, 4.0f, static_cast(10), 7UL); LOG_INFO(logger, "fox example logging {} {} {} {} {} {} {}", 3.0, 5L, 8ULL, std::string_view("view2"), 2, std::string("str2"), 4.0f); LOG_INFO(logger, "brown fox over lazy {} {} {} {} {} {}", false, static_cast(9), std::string_view("view1"), "example2", true, 6LL); LOG_INFO(logger, "quick logging over {} {} {} {} {} {} {}", 5L, 4.0f, std::string("str2"), "example1", 2, std::string_view("view1"), 7UL); LOG_INFO(logger, "example lazy brown dog {} {} {} {} {} {} {} {} {}", "example1", false, 3.0, 4.0f, "example3", std::string("str1"), "example2", 7UL, true); LOG_INFO(logger, "over dog test lazy {} {}", static_cast(10), 6LL); LOG_INFO(logger, "quick over dog example {} {} {} {}", 3.0, false, "example3", 7UL); LOG_INFO(logger, "example test quick {} {} {} {} {} {} {} {} {} {}", true, std::string_view("view1"), 4.0f, std::string("str2"), 2, static_cast(10), 3.0, 7UL, 1, std::string_view("view2")); LOG_INFO(logger, "over dog quick {} {} {} {} {} {} {} {} {} {}", 4.0f, std::string("str1"), 7UL, 2, 6LL, static_cast(10), 8ULL, std::string_view("view1"), true, 3.0); LOG_INFO(logger, "lazy test fox {} {}", 5L, 1); LOG_INFO(logger, "test over dog {} {} {} {} {} {}", std::string("str2"), "example2", 7UL, std::string_view("view2"), 8ULL, false); LOG_INFO(logger, "brown fox test jumps {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), 4.0f, 2, std::string("str1"), 1); LOG_INFO(logger, "over fox lazy {} {} {} {} {} {} {} {} {}", false, 2, static_cast(9), 4.0f, std::string("str2"), "example3", 1, std::string("str1"), std::string_view("view1")); LOG_INFO(logger, "fox example quick logging {} {}", "example2", 6LL); LOG_INFO(logger, "jumps dog fox {} {}", 6LL, 4.0f); LOG_INFO(logger, "dog brown test logging {} {} {} {}", std::string("str2"), std::string_view("view2"), 1, std::string_view("view1")); LOG_INFO(logger, "over brown dog test {} {} {} {} {} {} {}", 3.0, std::string("str1"), "example1", "example2", 6LL, 7UL, static_cast(9)); LOG_INFO(logger, "jumps example lazy brown {} {} {} {}", "example3", 4.0f, std::string_view("view1"), "example1"); LOG_INFO(logger, "over example dog {} {} {} {}", true, 1, false, std::string_view("view1")); LOG_INFO(logger, "test over logging {} {} {} {} {} {} {} {} {}", 5L, std::string_view("view2"), 6LL, std::string_view("view1"), 1, true, "example1", std::string("str2"), "example2"); LOG_INFO(logger, "lazy example jumps quick {} {} {} {} {} {} {} {}", std::string_view("view2"), std::string_view("view1"), static_cast(10), std::string("str2"), "example1", static_cast(9), 7UL, 6LL); LOG_INFO(logger, "jumps quick over brown {} {} {} {} {}", static_cast(9), true, 2, std::string_view("view2"), "example3"); LOG_INFO(logger, "lazy dog logging {} {} {} {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), 5L, std::string_view("view1"), "example2", 8ULL, 6LL, static_cast(9), 3.0); LOG_INFO(logger, "quick jumps brown {} {} {} {} {} {} {} {} {} {}", 1, true, std::string_view("view1"), 3.0, "example2", 4.0f, std::string("str2"), "example1", std::string_view("view2"), std::string("str1")); LOG_INFO(logger, "over brown logging dog {} {} {} {} {}", std::string("str1"), 3.0, 8ULL, static_cast(9), false); LOG_INFO(logger, "jumps brown over {}", "example1"); LOG_INFO(logger, "lazy test quick {} {} {} {} {}", 2, false, true, static_cast(10), 1); LOG_INFO(logger, "dog fox lazy brown {} {} {}", 6LL, std::string("str1"), "example3"); LOG_INFO(logger, "test jumps logging {} {} {} {} {} {} {} {}", 3.0, static_cast(9), 7UL, std::string("str2"), 1, "example1", 8ULL, true); LOG_INFO(logger, "quick lazy jumps fox {} {} {} {}", "example2", std::string_view("view2"), "example1", 4.0f); LOG_INFO(logger, "logging jumps brown {} {}", "example1", 5L); LOG_INFO(logger, "brown example over {} {} {} {} {} {} {}", std::string("str1"), std::string("str2"), 8ULL, 3.0, static_cast(9), true, std::string_view("view1")); LOG_INFO(logger, "over jumps brown {} {} {} {} {} {}", std::string_view("view1"), 4.0f, 2, std::string("str2"), 3.0, 6LL); LOG_INFO(logger, "quick jumps logging test {} {} {} {}", false, std::string("str1"), std::string_view("view1"), 8ULL); LOG_INFO(logger, "jumps fox lazy dog {} {} {} {} {} {} {} {} {}", true, static_cast(10), std::string_view("view1"), "example1", 7UL, static_cast(9), "example2", 8ULL, 1); LOG_INFO(logger, "logging over test dog {}", std::string("str1")); LOG_INFO(logger, "quick logging test lazy {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 8ULL, 1, 3.0, std::string_view("view2"), 6LL, true, 7UL, static_cast(10), "example1"); LOG_INFO(logger, "lazy over example brown {} {}", 2, 8ULL); LOG_INFO(logger, "dog logging quick test {} {} {} {} {}", true, false, 2, 6LL, "example1"); LOG_INFO(logger, "example test jumps {} {} {} {} {} {} {} {} {}", false, "example1", std::string_view("view2"), 6LL, std::string("str1"), 3.0, 7UL, 4.0f, "example3"); LOG_INFO(logger, "dog logging jumps {} {} {} {} {} {}", 3.0, 2, "example2", true, false, static_cast(9)); LOG_INFO(logger, "example test fox {}", 4.0f); LOG_INFO(logger, "brown logging example {} {} {} {}", std::string("str1"), 1, "example3", 3.0); LOG_INFO(logger, "dog jumps fox quick {} {} {} {} {} {} {} {} {} {}", static_cast(9), "example1", "example2", static_cast(10), 2, true, 8ULL, std::string_view("view1"), 1, 7UL); LOG_INFO(logger, "over dog fox lazy {} {} {} {} {} {} {} {} {} {}", 8ULL, 6LL, std::string_view("view2"), 3.0, std::string("str2"), 2, static_cast(9), "example3", static_cast(10), "example1"); LOG_INFO(logger, "brown test logging {} {} {} {} {} {} {} {} {}", 3.0, std::string("str2"), 2, std::string_view("view1"), "example1", 6LL, true, std::string_view("view2"), false); LOG_INFO(logger, "lazy fox brown {} {} {}", static_cast(9), std::string_view("view2"), "example1"); LOG_INFO(logger, "jumps lazy fox quick {} {} {} {} {} {} {} {}", false, 4.0f, 2, "example3", std::string("str1"), true, "example1", 3.0); LOG_INFO(logger, "lazy logging over {} {} {} {} {} {}", "example2", "example1", std::string("str1"), false, 2, std::string_view("view2")); LOG_INFO(logger, "test dog jumps example {} {} {}", static_cast(9), static_cast(10), 8ULL); LOG_INFO(logger, "example dog over quick {} {} {} {} {} {} {} {} {} {}", true, 1, std::string("str1"), std::string_view("view1"), "example1", 3.0, false, 2, "example3", static_cast(10)); LOG_INFO(logger, "brown test example over {} {} {} {} {} {}", 8ULL, 3.0, std::string("str1"), "example2", 5L, true); LOG_INFO(logger, "brown example jumps {} {} {} {} {} {} {}", 7UL, false, 6LL, 3.0, "example1", static_cast(9), 8ULL); LOG_INFO(logger, "dog fox jumps {} {} {} {} {} {} {} {}", 6LL, 5L, 8ULL, 1, true, 2, std::string("str2"), std::string_view("view1")); LOG_INFO(logger, "brown quick test {} {}", static_cast(10), 6LL); LOG_INFO(logger, "logging brown fox {} {} {} {}", true, 5L, 7UL, 3.0); LOG_INFO(logger, "test jumps lazy brown {}", "example2"); LOG_INFO(logger, "logging test lazy {}", true); LOG_INFO(logger, "lazy fox dog example {} {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), std::string("str1"), 5L, 7UL, static_cast(9), "example1", 3.0, "example2", 6LL); LOG_INFO(logger, "lazy test example logging {} {} {} {} {} {} {} {} {} {}", 6LL, "example3", false, 8ULL, std::string("str1"), "example1", 3.0, true, 4.0f, 7UL); LOG_INFO(logger, "dog logging over quick {} {}", 4.0f, false); LOG_INFO(logger, "logging brown fox {}", "example3"); LOG_INFO(logger, "dog logging brown {} {} {} {} {} {} {} {}", "example3", std::string_view("view1"), static_cast(10), "example2", std::string_view("view2"), 2, 8ULL, "example1"); LOG_INFO(logger, "brown over dog {} {} {} {} {} {} {} {} {} {}", "example1", 6LL, 4.0f, true, std::string_view("view1"), 1, 3.0, static_cast(9), "example3", 5L); LOG_INFO(logger, "logging example test quick {} {} {} {} {} {} {} {} {}", std::string("str1"), std::string_view("view2"), "example3", "example2", 8ULL, static_cast(9), 1, static_cast(10), false); LOG_INFO(logger, "fox over lazy jumps {} {} {} {} {} {} {} {} {}", 1, false, std::string_view("view1"), 6LL, 4.0f, 5L, 3.0, static_cast(9), 7UL); LOG_INFO(logger, "lazy test example over {} {} {} {} {} {} {} {} {}", static_cast(9), "example3", "example1", "example2", 8ULL, std::string("str1"), false, 6LL, 3.0); LOG_INFO(logger, "over logging fox brown {} {} {} {} {} {} {} {} {}", "example3", 3.0, 4.0f, std::string_view("view1"), 7UL, true, 6LL, std::string("str2"), 2); LOG_INFO(logger, "jumps lazy brown logging {} {} {}", "example3", std::string_view("view1"), 6LL); LOG_INFO(logger, "brown jumps lazy {}", static_cast(10)); LOG_INFO(logger, "test quick brown {} {} {}", "example1", false, std::string_view("view1")); LOG_INFO(logger, "fox brown over {} {} {} {} {} {} {} {} {}", 2, "example3", 3.0, 4.0f, std::string_view("view2"), "example2", 1, std::string("str1"), 7UL); LOG_INFO(logger, "fox logging jumps example {} {} {} {} {}", "example1", 4.0f, static_cast(10), "example2", true); LOG_INFO(logger, "quick over jumps fox {} {} {} {} {} {} {} {}", 8ULL, 1, 4.0f, std::string_view("view2"), 2, static_cast(10), std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "logging dog brown {} {}", 5L, std::string_view("view1")); LOG_INFO(logger, "fox example brown dog {} {} {}", 2, "example1", 4.0f); LOG_INFO(logger, "brown logging dog fox {} {} {} {} {} {} {} {} {} {}", false, 5L, 8ULL, std::string("str1"), 2, "example2", 3.0, static_cast(10), 1, "example3"); LOG_INFO(logger, "over jumps fox {} {} {} {} {} {} {}", static_cast(10), std::string_view("view2"), static_cast(9), 2, 4.0f, std::string_view("view1"), "example3"); LOG_INFO(logger, "example fox logging {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 4.0f, std::string("str1"), 5L, static_cast(9), 8ULL, 7UL, static_cast(10), 3.0, 6LL); LOG_INFO(logger, "fox jumps dog {} {}", 4.0f, true); LOG_INFO(logger, "quick over example {} {} {} {} {} {}", 7UL, std::string("str2"), 5L, "example1", false, 1); LOG_INFO(logger, "brown lazy over logging {} {} {} {} {} {} {} {}", std::string("str2"), 1, 8ULL, static_cast(10), 5L, 4.0f, true, 3.0); LOG_INFO(logger, "over jumps example {} {} {} {} {} {} {}", 5L, "example3", 4.0f, 7UL, "example2", static_cast(10), true); LOG_INFO(logger, "jumps brown example {} {} {} {} {} {} {}", 2, 8ULL, 1, std::string("str1"), std::string_view("view1"), false, static_cast(10)); LOG_INFO(logger, "jumps quick brown lazy {} {}", false, 8ULL); LOG_INFO(logger, "example quick lazy {} {} {} {} {} {} {} {} {} {}", 3.0, 2, static_cast(10), 7UL, 6LL, std::string("str1"), 1, std::string("str2"), "example3", std::string_view("view1")); LOG_INFO(logger, "lazy logging quick {} {} {} {} {} {} {} {}", 4.0f, true, 1, 5L, 3.0, 2, std::string_view("view1"), static_cast(10)); LOG_INFO(logger, "lazy brown dog fox {} {} {} {} {} {} {} {} {}", std::string_view("view2"), false, static_cast(9), "example1", 4.0f, 7UL, static_cast(10), 3.0, "example3"); LOG_INFO(logger, "quick logging brown over {} {} {} {} {} {}", std::string_view("view2"), "example2", 6LL, static_cast(9), static_cast(10), 4.0f); LOG_INFO(logger, "logging fox example {} {} {} {} {} {} {}", 5L, std::string_view("view2"), 6LL, "example3", 7UL, std::string("str1"), 2); LOG_INFO(logger, "jumps lazy quick dog {} {} {} {}", 7UL, 5L, 6LL, std::string("str1")); LOG_INFO(logger, "jumps over lazy {} {} {} {} {} {}", "example2", static_cast(9), 8ULL, 5L, 1, "example3"); LOG_INFO(logger, "dog jumps fox {} {} {} {} {}", 3.0, std::string_view("view2"), 8ULL, static_cast(9), 2); LOG_INFO(logger, "quick example fox {} {} {} {} {}", 8ULL, true, 7UL, static_cast(9), "example2"); LOG_INFO(logger, "test quick fox logging {} {} {} {} {} {}", "example1", false, std::string("str2"), static_cast(9), 3.0, "example2"); LOG_INFO(logger, "jumps logging example quick {} {} {}", 4.0f, std::string("str1"), 8ULL); LOG_INFO(logger, "dog brown logging {} {}", false, "example2"); LOG_INFO(logger, "dog fox brown quick {} {} {} {} {}", "example3", 1, std::string_view("view1"), static_cast(9), 8ULL); LOG_INFO(logger, "quick jumps test dog {} {}", 7UL, 8ULL); LOG_INFO(logger, "fox example quick {} {} {} {} {} {} {} {} {} {}", 2, 4.0f, 1, 6LL, std::string("str1"), "example2", std::string_view("view1"), 7UL, false, static_cast(10)); LOG_INFO(logger, "test quick logging {} {} {} {} {} {} {}", std::string("str2"), false, 2, 7UL, 8ULL, 4.0f, static_cast(9)); LOG_INFO(logger, "over test brown {} {} {} {} {} {} {} {} {} {}", 8ULL, 6LL, false, true, "example1", "example2", 7UL, std::string("str1"), 5L, std::string_view("view1")); LOG_INFO(logger, "test example over lazy {}", 8ULL); LOG_INFO(logger, "quick dog over {}", 4.0f); LOG_INFO(logger, "example quick jumps {} {} {}", 8ULL, std::string("str2"), 4.0f); LOG_INFO(logger, "fox brown lazy {} {} {} {} {}", 3.0, false, static_cast(10), "example1", 1); LOG_INFO(logger, "quick lazy jumps brown {} {} {} {} {} {} {}", static_cast(10), 7UL, true, std::string("str1"), 1, "example1", std::string_view("view1")); LOG_INFO(logger, "over jumps logging quick {} {} {} {} {}", "example3", std::string("str2"), true, 5L, 2); LOG_INFO(logger, "quick fox logging {} {} {} {}", 6LL, 2, 7UL, 1); LOG_INFO(logger, "dog fox quick jumps {} {}", 6LL, static_cast(9)); LOG_INFO(logger, "dog over jumps fox {} {}", true, 5L); LOG_INFO(logger, "logging example dog jumps {} {} {} {}", 4.0f, "example2", static_cast(9), std::string_view("view1")); LOG_INFO(logger, "logging fox test {} {} {} {} {} {} {} {} {} {}", "example1", 7UL, "example2", 2, 1, 3.0, std::string("str2"), 5L, 4.0f, "example3"); LOG_INFO(logger, "logging fox quick brown {} {} {}", "example1", 3.0, 6LL); LOG_INFO(logger, "quick lazy brown test {} {} {} {}", "example1", std::string_view("view1"), std::string("str1"), std::string_view("view2")); LOG_INFO(logger, "over fox dog {} {} {} {} {} {} {} {}", "example1", static_cast(10), true, 5L, std::string_view("view2"), 3.0, std::string("str1"), 2); LOG_INFO(logger, "jumps logging over {} {} {} {} {} {} {} {} {} {}", 8ULL, std::string("str2"), 7UL, "example3", 4.0f, static_cast(10), std::string_view("view1"), 2, 3.0, 6LL); LOG_INFO(logger, "jumps fox over {} {} {} {}", std::string_view("view2"), 5L, 7UL, std::string_view("view1")); LOG_INFO(logger, "example brown over jumps {}", 7UL); LOG_INFO(logger, "fox example jumps test {}", true); LOG_INFO(logger, "fox test over {} {} {}", std::string_view("view1"), "example3", std::string("str1")); LOG_INFO(logger, "logging dog brown over {} {} {} {} {}", 6LL, std::string_view("view2"), std::string("str2"), 5L, "example1"); LOG_INFO(logger, "fox example dog {} {} {} {} {} {}", 2, 1, static_cast(10), 4.0f, std::string("str2"), std::string_view("view2")); LOG_INFO(logger, "fox dog jumps {} {} {} {} {} {} {} {} {}", "example2", std::string("str1"), std::string_view("view2"), std::string_view("view1"), 8ULL, 4.0f, 2, "example3", static_cast(10)); LOG_INFO(logger, "fox logging dog {} {} {} {} {} {} {} {}", "example1", 1, std::string("str1"), static_cast(10), "example2", false, 6LL, "example3"); LOG_INFO(logger, "quick test jumps {} {} {} {}", std::string("str2"), 6LL, static_cast(10), false); LOG_INFO(logger, "over fox quick dog {} {} {} {} {} {}", std::string("str1"), true, std::string("str2"), 4.0f, 7UL, 2); LOG_INFO(logger, "fox dog test {} {} {} {} {}", "example1", std::string("str1"), 6LL, static_cast(10), false); LOG_INFO(logger, "brown jumps example over {} {} {} {} {} {} {} {} {}", std::string("str2"), static_cast(9), 5L, "example2", std::string("str1"), "example3", std::string_view("view2"), 4.0f, 3.0); LOG_INFO(logger, "quick logging dog {} {} {} {} {} {} {} {} {} {}", std::string("str2"), false, 8ULL, std::string("str1"), 3.0, 5L, 4.0f, 6LL, 7UL, "example2"); LOG_INFO(logger, "fox dog quick {} {} {} {} {}", 3.0, true, 4.0f, 2, "example1"); LOG_INFO(logger, "quick brown over logging {}", 2); LOG_INFO(logger, "dog logging example {} {} {}", "example3", 1, "example1"); LOG_INFO(logger, "logging over jumps {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 4.0f, static_cast(10), std::string_view("view1"), "example3", "example1", std::string("str2"), "example2", 3.0, 6LL); LOG_INFO(logger, "jumps quick over {} {} {} {} {} {} {}", "example1", false, true, "example3", 5L, std::string("str2"), static_cast(10)); LOG_INFO(logger, "logging lazy brown fox {}", 6LL); LOG_INFO(logger, "over quick brown dog {} {} {} {}", "example3", std::string("str2"), 1, 4.0f); LOG_INFO(logger, "brown logging fox jumps {} {} {}", true, 5L, 2); LOG_INFO(logger, "example test fox {} {}", true, 1); LOG_INFO(logger, "quick test fox logging {} {} {} {} {} {}", static_cast(10), 8ULL, 4.0f, std::string("str1"), 7UL, false); LOG_INFO(logger, "dog logging fox test {} {} {} {} {} {} {}", false, "example3", static_cast(10), 5L, 2, 6LL, std::string("str1")); LOG_INFO(logger, "dog example jumps {} {}", std::string("str1"), 7UL); LOG_INFO(logger, "dog over jumps test {} {} {} {} {} {} {}", std::string("str2"), false, 4.0f, std::string_view("view1"), static_cast(10), true, 7UL); LOG_INFO(logger, "lazy fox brown dog {} {}", std::string_view("view2"), 5L); LOG_INFO(logger, "over quick test example {} {} {} {} {} {} {}", 7UL, 5L, 8ULL, 1, static_cast(9), std::string_view("view2"), std::string("str2")); LOG_INFO(logger, "brown over fox example {} {} {} {} {} {} {} {}", static_cast(10), 5L, std::string_view("view1"), std::string("str2"), static_cast(9), 8ULL, "example3", 3.0); LOG_INFO(logger, "logging jumps brown {} {} {} {}", 7UL, 3.0, true, "example1"); LOG_INFO(logger, "brown quick logging example {} {} {} {} {}", "example2", static_cast(10), 5L, static_cast(9), 6LL); LOG_INFO(logger, "jumps logging fox over {} {} {} {} {} {} {} {}", 3.0, 2, "example2", "example1", 4.0f, std::string("str1"), std::string_view("view2"), true); LOG_INFO(logger, "over logging lazy dog {}", 6LL); LOG_INFO(logger, "dog lazy over {}", std::string("str1")); LOG_INFO(logger, "jumps over logging dog {} {} {} {} {} {} {} {}", 4.0f, "example1", 8ULL, false, 2, 5L, static_cast(9), std::string_view("view1")); LOG_INFO(logger, "brown quick jumps {} {} {} {} {} {} {} {}", std::string_view("view2"), true, "example1", 8ULL, static_cast(10), std::string("str2"), "example2", std::string_view("view1")); LOG_INFO(logger, "logging dog lazy {} {} {}", "example3", std::string_view("view1"), std::string("str1")); LOG_INFO(logger, "test logging fox {} {}", 7UL, 8ULL); LOG_INFO(logger, "fox brown lazy {} {} {} {} {} {} {} {}", static_cast(10), static_cast(9), 1, 8ULL, false, "example2", std::string("str1"), 7UL); LOG_INFO(logger, "example fox dog {} {}", "example3", std::string_view("view2")); LOG_INFO(logger, "logging dog jumps {} {} {} {} {} {} {} {} {}", "example3", std::string_view("view2"), static_cast(10), static_cast(9), 7UL, 1, "example2", std::string("str1"), true); LOG_INFO(logger, "example fox brown {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), 4.0f, 5L, 6LL, "example2", true, 2, "example1", std::string("str2")); LOG_INFO(logger, "fox over example {} {} {} {} {} {} {} {}", static_cast(10), 2, 3.0, std::string("str1"), std::string("str2"), true, 1, "example3"); LOG_INFO(logger, "example jumps brown fox {} {}", false, std::string_view("view2")); LOG_INFO(logger, "brown jumps dog logging {} {} {} {} {} {} {} {}", 7UL, "example2", 6LL, std::string_view("view1"), 1, static_cast(9), std::string("str2"), 5L); LOG_INFO(logger, "example test quick logging {} {} {} {} {} {} {}", std::string_view("view1"), true, std::string("str2"), 7UL, std::string_view("view2"), "example3", 3.0); LOG_INFO(logger, "over lazy example jumps {} {} {} {} {} {} {}", std::string_view("view2"), "example2", std::string_view("view1"), 8ULL, 6LL, false, 3.0); LOG_INFO(logger, "jumps dog quick logging {} {}", "example2", std::string_view("view2")); LOG_INFO(logger, "lazy example fox test {} {}", std::string("str2"), "example1"); LOG_INFO(logger, "example quick jumps {}", "example2"); LOG_INFO(logger, "quick fox example {} {} {} {} {} {} {}", "example2", std::string("str2"), 1, 8ULL, true, "example1", 3.0); LOG_INFO(logger, "lazy jumps dog {} {} {} {} {} {} {} {}", std::string_view("view1"), static_cast(10), std::string_view("view2"), 7UL, std::string("str2"), false, 1, 6LL); LOG_INFO(logger, "fox lazy over {} {} {}", static_cast(9), 4.0f, "example1"); LOG_INFO(logger, "brown quick jumps test {} {} {} {} {} {} {} {}", 5L, 4.0f, std::string_view("view2"), "example2", "example1", true, false, 2); LOG_INFO(logger, "brown fox quick {} {} {}", "example3", static_cast(9), std::string("str2")); LOG_INFO(logger, "lazy dog quick {} {} {} {} {} {}", 8ULL, "example1", 7UL, "example3", 3.0, 4.0f); LOG_INFO(logger, "over dog test {} {} {} {} {}", static_cast(9), std::string("str2"), std::string_view("view1"), std::string("str1"), true); LOG_INFO(logger, "quick brown logging {} {} {} {} {} {} {} {} {} {}", 1, 2, "example2", std::string("str2"), 5L, false, static_cast(10), std::string("str1"), std::string_view("view2"), "example1"); LOG_INFO(logger, "dog over test {}", std::string("str2")); LOG_INFO(logger, "example logging fox test {} {} {}", true, 2, std::string_view("view1")); LOG_INFO(logger, "logging fox quick {} {} {} {} {}", "example3", 6LL, true, 4.0f, 7UL); LOG_INFO(logger, "logging brown test jumps {} {} {} {} {}", 2, 3.0, "example2", 5L, static_cast(9)); LOG_INFO(logger, "dog example logging lazy {} {} {}", "example2", "example1", 2); LOG_INFO(logger, "logging fox lazy jumps {} {} {} {} {} {} {}", static_cast(10), false, "example2", 8ULL, "example1", "example3", 6LL); LOG_INFO(logger, "test logging quick over {}", "example1"); LOG_INFO(logger, "test quick example {} {}", "example1", 1); LOG_INFO(logger, "dog lazy test brown {} {} {} {} {} {} {} {} {} {}", 5L, 2, true, std::string("str1"), "example2", std::string_view("view2"), 1, static_cast(10), 3.0, 6LL); LOG_INFO(logger, "over brown jumps fox {} {} {} {} {} {} {} {} {} {}", static_cast(10), 2, "example1", 6LL, "example3", 7UL, std::string_view("view2"), 3.0, "example2", std::string_view("view1")); LOG_INFO(logger, "dog quick test brown {} {} {} {}", std::string("str1"), "example2", std::string("str2"), 8ULL); LOG_INFO(logger, "logging fox brown {} {} {} {} {} {}", std::string("str1"), 6LL, 1, "example1", 4.0f, true); LOG_INFO(logger, "jumps over test quick {} {} {} {} {} {} {}", std::string("str2"), 6LL, true, "example2", 7UL, 5L, 3.0); LOG_INFO(logger, "example logging over {} {} {} {} {}", std::string("str1"), 5L, "example2", false, 7UL); LOG_INFO(logger, "example quick fox dog {} {} {} {} {} {}", std::string_view("view2"), static_cast(9), std::string("str1"), std::string("str2"), false, 1); LOG_INFO(logger, "example dog lazy {} {} {}", 2, 6LL, 8ULL); LOG_INFO(logger, "dog lazy example {} {} {} {} {} {}", 5L, "example2", "example3", 7UL, std::string("str1"), 1); LOG_INFO(logger, "brown lazy logging quick {}", static_cast(9)); LOG_INFO(logger, "jumps test dog fox {} {} {} {} {} {} {} {}", 7UL, "example1", 5L, 6LL, 8ULL, false, true, 4.0f); LOG_INFO(logger, "dog quick logging test {} {} {} {} {}", 3.0, 2, true, 5L, std::string_view("view1")); LOG_INFO(logger, "dog over lazy {} {} {} {} {} {} {}", 5L, "example3", std::string("str1"), "example2", 6LL, 8ULL, std::string("str2")); LOG_INFO(logger, "example quick jumps {} {} {} {}", "example2", static_cast(10), false, 7UL); LOG_INFO(logger, "quick fox brown {}", true); LOG_INFO(logger, "jumps over lazy dog {} {} {} {} {} {} {}", 7UL, 6LL, 8ULL, false, 5L, 3.0, 2); LOG_INFO(logger, "brown quick logging {} {} {}", 1, static_cast(10), std::string("str1")); LOG_INFO(logger, "jumps lazy example {} {} {} {} {}", 1, static_cast(10), 6LL, 5L, "example1"); LOG_INFO(logger, "example jumps quick {} {} {} {} {} {}", std::string_view("view1"), std::string_view("view2"), 7UL, 3.0, 6LL, "example1"); LOG_INFO(logger, "over jumps logging {} {} {} {} {} {} {} {} {} {}", 2, "example1", 4.0f, 6LL, 7UL, 3.0, std::string_view("view2"), 1, static_cast(9), 8ULL); LOG_INFO(logger, "lazy jumps dog {} {} {} {}", static_cast(9), 5L, 2, 4.0f); LOG_INFO(logger, "fox dog jumps example {} {} {} {} {} {} {} {} {}", 5L, "example1", 4.0f, 2, 8ULL, static_cast(9), "example2", 6LL, 7UL); LOG_INFO(logger, "logging fox lazy jumps {} {} {} {} {} {} {} {} {}", 2, std::string("str1"), std::string_view("view2"), std::string_view("view1"), 4.0f, false, "example2", 5L, static_cast(10)); LOG_INFO(logger, "test quick brown example {} {} {} {} {} {} {}", 3.0, false, std::string("str1"), true, 7UL, "example1", 2); LOG_INFO(logger, "dog fox jumps {} {} {} {} {} {} {} {} {}", 4.0f, 1, 2, "example1", static_cast(9), "example3", 5L, 3.0, std::string("str2")); LOG_INFO(logger, "dog fox brown {} {} {} {}", 2, 1, std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "lazy test brown example {} {} {} {} {} {}", "example1", true, "example2", std::string("str2"), static_cast(9), 3.0); LOG_INFO(logger, "logging brown quick example {} {}", 5L, std::string("str1")); LOG_INFO(logger, "example fox lazy dog {} {} {} {} {} {} {}", true, 1, static_cast(10), false, 5L, "example2", 6LL); LOG_INFO(logger, "logging dog brown quick {} {} {} {} {}", static_cast(9), 1, std::string("str1"), 7UL, 4.0f); LOG_INFO(logger, "logging lazy quick {}", false); LOG_INFO(logger, "over lazy jumps {} {} {} {}", "example3", "example2", "example1", 2); LOG_INFO(logger, "lazy dog fox {} {} {} {} {}", "example1", true, 3.0, std::string("str1"), static_cast(10)); LOG_INFO(logger, "over logging example dog {} {} {} {} {} {}", true, static_cast(10), 1, "example1", std::string_view("view2"), "example3"); LOG_INFO(logger, "brown lazy example {} {} {} {} {} {} {}", 1, 6LL, 7UL, "example2", "example1", std::string_view("view2"), false); LOG_INFO(logger, "example over test {} {} {} {}", true, std::string_view("view1"), static_cast(9), static_cast(10)); LOG_INFO(logger, "test dog fox {} {} {} {} {} {} {} {}", "example3", std::string("str2"), "example2", 3.0, 7UL, true, std::string_view("view1"), 6LL); LOG_INFO(logger, "dog test fox {}", std::string_view("view1")); LOG_INFO(logger, "jumps over lazy {} {} {} {} {}", std::string_view("view2"), false, "example3", 3.0, 4.0f); LOG_INFO(logger, "example test over logging {} {} {} {} {} {} {} {} {}", 3.0, std::string("str2"), std::string("str1"), 4.0f, 8ULL, 1, std::string_view("view1"), static_cast(10), 7UL); LOG_INFO(logger, "quick dog logging {} {} {} {} {} {} {} {}", static_cast(9), 8ULL, true, 2, std::string("str1"), "example1", 1, 3.0); LOG_INFO(logger, "quick logging jumps {} {}", "example3", "example1"); LOG_INFO(logger, "example brown quick {}", "example1"); LOG_INFO(logger, "jumps fox logging test {} {}", static_cast(9), 4.0f); LOG_INFO(logger, "jumps fox lazy over {} {} {} {}", "example3", std::string("str2"), "example2", 5L); LOG_INFO(logger, "example test logging {}", 7UL); LOG_INFO(logger, "quick example dog {} {} {} {} {} {} {}", 4.0f, 6LL, 8ULL, static_cast(10), true, "example3", 2); LOG_INFO(logger, "lazy test fox {} {}", static_cast(9), "example1"); LOG_INFO(logger, "logging lazy dog jumps {}", false); LOG_INFO(logger, "brown jumps lazy fox {} {} {} {} {} {} {}", 8ULL, "example3", "example1", std::string_view("view2"), 3.0, std::string("str1"), 2); LOG_INFO(logger, "lazy quick dog {} {} {} {} {}", 8ULL, std::string_view("view2"), 7UL, false, std::string_view("view1")); LOG_INFO(logger, "fox logging brown jumps {} {}", 8ULL, std::string("str1")); LOG_INFO(logger, "lazy quick brown example {} {} {} {}", 4.0f, "example3", true, false); LOG_INFO(logger, "dog example brown fox {} {} {} {} {} {} {} {} {}", false, 1, "example2", 4.0f, 8ULL, true, "example3", 2, std::string_view("view2")); LOG_INFO(logger, "test quick over example {} {} {} {} {} {} {} {} {} {}", 2, std::string_view("view2"), 3.0, 4.0f, false, "example2", 6LL, "example3", 5L, 7UL); LOG_INFO(logger, "over dog fox {} {}", "example3", 8ULL); LOG_INFO(logger, "fox over jumps {} {}", 3.0, 2); LOG_INFO(logger, "jumps quick lazy over {} {}", static_cast(9), 1); LOG_INFO(logger, "logging fox jumps {} {} {} {} {} {}", static_cast(10), std::string_view("view1"), "example2", 2, 4.0f, 6LL); LOG_INFO(logger, "lazy jumps example test {} {} {}", static_cast(10), 3.0, true); LOG_INFO(logger, "lazy quick dog over {} {} {} {} {} {} {} {}", "example2", static_cast(10), std::string("str2"), false, true, std::string_view("view1"), 8ULL, "example3"); LOG_INFO(logger, "logging test fox {} {} {} {}", static_cast(10), std::string_view("view2"), false, "example2"); LOG_INFO(logger, "example quick over {} {} {} {} {} {} {} {}", "example3", std::string_view("view1"), 4.0f, std::string("str1"), true, static_cast(9), "example2", 1); LOG_INFO(logger, "fox jumps quick lazy {} {}", 6LL, 1); LOG_INFO(logger, "fox jumps logging brown {} {} {} {} {} {} {} {} {} {}", static_cast(9), 1, std::string("str1"), "example2", 5L, "example3", std::string_view("view2"), 8ULL, 4.0f, 2); LOG_INFO(logger, "test over fox lazy {} {} {}", false, std::string("str2"), "example3"); LOG_INFO(logger, "jumps brown fox dog {} {} {} {}", true, 8ULL, std::string("str2"), "example3"); LOG_INFO(logger, "quick fox lazy dog {} {} {} {} {} {} {}", 7UL, "example1", 3.0, 4.0f, static_cast(9), static_cast(10), 5L); LOG_INFO(logger, "lazy example logging {} {} {} {} {} {} {} {} {} {}", true, 1, 7UL, 8ULL, std::string("str2"), std::string_view("view1"), 2, false, 6LL, "example3"); LOG_INFO(logger, "dog brown logging {} {} {}", static_cast(10), 8ULL, 7UL); LOG_INFO(logger, "test example lazy logging {} {} {} {} {} {} {} {}", 8ULL, 3.0, 5L, 4.0f, std::string_view("view1"), std::string("str2"), static_cast(10), "example1"); LOG_INFO(logger, "dog logging over {} {} {} {} {} {}", 2, std::string("str2"), static_cast(9), 8ULL, "example3", static_cast(10)); LOG_INFO(logger, "test fox over {} {} {} {} {} {}", true, static_cast(9), 5L, 1, std::string_view("view2"), "example2"); LOG_INFO(logger, "lazy fox logging {} {} {}", 3.0, std::string_view("view1"), std::string_view("view2")); LOG_INFO(logger, "logging over example test {} {} {} {} {} {} {}", std::string_view("view1"), std::string("str2"), 2, "example3", 4.0f, 5L, "example1"); LOG_INFO(logger, "fox example lazy over {} {} {} {} {} {} {} {}", "example1", false, true, 2, 5L, static_cast(10), "example2", 7UL); LOG_INFO(logger, "example fox lazy test {} {} {} {} {} {} {}", std::string_view("view2"), std::string("str2"), static_cast(9), std::string_view("view1"), 7UL, "example2", 6LL); LOG_INFO(logger, "quick test jumps example {} {} {} {}", "example3", 6LL, std::string_view("view1"), 3.0); LOG_INFO(logger, "jumps over brown example {} {}", 4.0f, 8ULL); LOG_INFO(logger, "jumps quick dog {} {} {} {} {} {}", 3.0, 8ULL, 7UL, 5L, "example1", std::string("str1")); LOG_INFO(logger, "quick dog brown lazy {} {} {} {}", 2, true, 8ULL, static_cast(9)); LOG_INFO(logger, "quick fox jumps {} {} {} {} {} {} {} {} {}", 8ULL, 7UL, static_cast(9), 2, 4.0f, 1, std::string_view("view2"), std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "lazy example test logging {} {} {} {} {} {} {} {} {} {}", 5L, 2, 3.0, std::string("str1"), "example2", std::string_view("view2"), 1, std::string("str2"), true, "example1"); LOG_INFO(logger, "fox lazy jumps {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), "example1", std::string_view("view1"), 2, 6LL, 4.0f, "example2", static_cast(10), 1, true); LOG_INFO(logger, "dog test quick jumps {} {} {}", static_cast(10), 1, 6LL); LOG_INFO(logger, "logging brown dog quick {} {} {} {}", true, 6LL, 4.0f, static_cast(9)); LOG_INFO(logger, "lazy over dog logging {} {} {} {} {} {} {}", "example2", "example3", 4.0f, 5L, true, static_cast(10), std::string("str1")); LOG_INFO(logger, "lazy quick logging {} {} {} {}", 3.0, std::string("str1"), 2, std::string("str2")); LOG_INFO(logger, "dog jumps logging lazy {} {}", 6LL, 4.0f); LOG_INFO(logger, "logging fox dog quick {} {} {} {} {} {} {} {}", std::string_view("view1"), "example2", true, "example1", 1, std::string_view("view2"), 7UL, 2); LOG_INFO(logger, "brown logging over {} {} {} {} {} {} {}", std::string("str1"), 5L, std::string("str2"), static_cast(10), "example3", 8ULL, "example1"); LOG_INFO(logger, "test fox dog {} {} {}", std::string("str2"), static_cast(10), 2); LOG_INFO(logger, "jumps fox brown {} {} {} {} {} {} {} {} {} {}", "example3", static_cast(9), 5L, 8ULL, 3.0, std::string_view("view2"), 2, "example1", 4.0f, 1); LOG_INFO(logger, "jumps lazy test dog {} {} {} {} {} {} {}", 3.0, true, 7UL, 4.0f, 6LL, std::string("str1"), 2); LOG_INFO(logger, "logging quick brown lazy {} {} {} {} {}", false, std::string_view("view2"), std::string_view("view1"), 1, "example1"); LOG_INFO(logger, "over brown fox logging {} {} {} {} {} {}", 5L, static_cast(9), std::string("str2"), "example3", std::string("str1"), 8ULL); LOG_INFO(logger, "quick brown logging {} {} {} {} {} {} {} {} {} {}", std::string("str1"), "example3", "example1", 5L, static_cast(9), 1, "example2", 7UL, 2, 8ULL); LOG_INFO(logger, "quick brown logging {} {} {} {} {} {} {} {} {} {}", static_cast(10), static_cast(9), std::string_view("view2"), 6LL, "example1", 7UL, 4.0f, false, std::string("str2"), 8ULL); LOG_INFO(logger, "fox dog lazy test {} {} {}", std::string("str2"), static_cast(9), 5L); LOG_INFO(logger, "quick example over {} {} {} {} {} {} {} {} {} {}", 6LL, std::string_view("view2"), static_cast(10), true, 2, static_cast(9), "example1", std::string("str1"), std::string("str2"), "example2"); LOG_INFO(logger, "over example fox {} {} {}", std::string("str2"), "example3", std::string_view("view1")); LOG_INFO(logger, "brown logging test {} {} {} {} {}", std::string("str1"), std::string_view("view1"), std::string("str2"), false, 1); LOG_INFO(logger, "logging quick test dog {} {} {} {} {}", 8ULL, std::string_view("view2"), std::string_view("view1"), "example1", true); LOG_INFO(logger, "dog example brown lazy {} {} {} {} {} {} {}", "example3", std::string_view("view1"), static_cast(10), 2, 5L, "example2", true); LOG_INFO(logger, "jumps brown fox {} {} {} {} {} {} {} {} {}", "example1", 4.0f, std::string("str1"), 8ULL, std::string_view("view1"), static_cast(9), "example3", true, std::string_view("view2")); LOG_INFO(logger, "logging over lazy {} {} {} {}", 2, false, 1, std::string_view("view2")); LOG_INFO(logger, "example quick brown fox {} {} {} {} {}", 6LL, false, 3.0, 2, static_cast(9)); LOG_INFO(logger, "test fox over logging {} {} {} {} {} {} {} {} {}", 2, 4.0f, 8ULL, 7UL, "example1", std::string_view("view2"), false, "example2", 5L); LOG_INFO(logger, "test lazy fox {} {} {} {} {} {}", 7UL, static_cast(9), 4.0f, std::string_view("view1"), "example2", "example3"); LOG_INFO(logger, "brown logging lazy {} {} {} {} {} {} {}", 4.0f, 7UL, std::string_view("view2"), 8ULL, static_cast(10), "example2", "example1"); LOG_INFO(logger, "test lazy over {} {} {} {} {} {} {} {} {} {}", 7UL, std::string_view("view2"), 2, true, "example1", 4.0f, false, std::string("str1"), "example2", "example3"); LOG_INFO(logger, "logging over test {} {} {} {}", 5L, "example1", static_cast(10), 7UL); LOG_INFO(logger, "over dog lazy quick {} {}", 8ULL, 6LL); LOG_INFO(logger, "brown example quick {}", "example1"); LOG_INFO(logger, "test logging example fox {} {} {} {} {} {} {} {} {}", static_cast(9), "example1", "example2", 4.0f, 3.0, std::string_view("view2"), 7UL, 5L, 8ULL); LOG_INFO(logger, "quick example fox {}", true); LOG_INFO(logger, "test dog fox {}", std::string_view("view1")); LOG_INFO(logger, "quick lazy over test {} {} {} {} {} {} {} {}", 8ULL, 2, std::string("str1"), "example2", "example1", 3.0, std::string_view("view1"), std::string_view("view2")); LOG_INFO(logger, "fox dog jumps {} {} {} {} {} {} {} {} {} {}", std::string("str1"), 7UL, "example1", 8ULL, 1, "example2", static_cast(9), std::string_view("view1"), 2, false); LOG_INFO(logger, "example logging quick dog {} {} {} {} {} {}", static_cast(9), "example2", std::string("str2"), 5L, 8ULL, std::string_view("view2")); LOG_INFO(logger, "logging dog quick fox {} {} {} {} {} {} {} {} {}", std::string("str1"), 4.0f, std::string("str2"), static_cast(9), 3.0, static_cast(10), std::string_view("view2"), "example1", 5L); LOG_INFO(logger, "over dog jumps {} {} {} {}", std::string_view("view2"), static_cast(9), 4.0f, static_cast(10)); LOG_INFO(logger, "logging example fox jumps {} {} {} {} {} {} {}", true, false, static_cast(9), 5L, 7UL, 6LL, std::string_view("view2")); LOG_INFO(logger, "over quick brown {} {} {} {} {} {} {} {}", 1, 2, false, true, 4.0f, std::string_view("view2"), static_cast(10), std::string("str2")); LOG_INFO(logger, "brown lazy logging {} {} {} {} {} {}", "example3", 3.0, static_cast(10), 8ULL, 6LL, std::string("str1")); LOG_INFO(logger, "example over dog {} {} {} {} {} {} {} {} {}", "example2", 2, 7UL, true, 8ULL, "example3", 4.0f, 1, false); LOG_INFO(logger, "example over fox {}", "example1"); LOG_INFO(logger, "over example brown {}", "example1"); LOG_INFO(logger, "over jumps fox lazy {} {} {} {} {} {} {} {} {} {}", 2, 4.0f, 8ULL, std::string_view("view1"), static_cast(9), true, std::string("str1"), "example2", std::string_view("view2"), 6LL); LOG_INFO(logger, "brown logging example {} {}", "example3", std::string_view("view2")); LOG_INFO(logger, "brown over fox {} {} {} {} {} {} {} {}", 1, "example1", std::string("str2"), true, std::string_view("view1"), std::string_view("view2"), 3.0, static_cast(9)); LOG_INFO(logger, "dog over quick {} {} {} {} {}", std::string("str2"), 8ULL, 4.0f, 5L, static_cast(9)); LOG_INFO(logger, "brown dog quick lazy {} {} {} {} {}", "example3", 3.0, 7UL, "example1", std::string("str1")); LOG_INFO(logger, "dog lazy logging quick {} {} {} {} {}", std::string_view("view1"), 6LL, 2, "example1", "example2"); LOG_INFO(logger, "over quick test {} {} {} {}", std::string("str1"), 3.0, 6LL, std::string_view("view1")); LOG_INFO(logger, "fox brown quick lazy {} {} {} {}", 3.0, "example3", 5L, std::string("str2")); LOG_INFO(logger, "example over lazy {} {} {}", 7UL, 5L, 6LL); LOG_INFO(logger, "quick example dog {} {} {} {}", "example1", std::string("str2"), std::string_view("view2"), 5L); LOG_INFO(logger, "example brown over logging {} {} {} {} {} {} {} {} {}", std::string("str2"), 6LL, "example3", "example2", 4.0f, false, static_cast(10), 1, 2); LOG_INFO(logger, "test brown quick {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 7UL, std::string_view("view1"), true, "example1", 6LL, static_cast(9), 1, std::string("str1"), 5L); LOG_INFO(logger, "brown dog jumps {} {} {} {} {} {} {} {} {} {}", 7UL, static_cast(10), false, true, 8ULL, 1, 4.0f, std::string("str1"), "example3", std::string_view("view2")); LOG_INFO(logger, "example lazy over test {} {} {} {} {}", 1, 3.0, 2, static_cast(10), 7UL); LOG_INFO(logger, "lazy quick fox example {} {} {} {} {} {}", "example3", "example2", 2, std::string("str1"), static_cast(10), 4.0f); LOG_INFO(logger, "quick fox dog lazy {} {} {} {} {} {} {} {} {} {}", 5L, std::string_view("view2"), 4.0f, 3.0, 2, std::string("str2"), "example1", 7UL, "example2", 6LL); LOG_INFO(logger, "quick jumps over {} {} {} {} {} {} {}", 3.0, true, 2, "example2", std::string("str2"), std::string_view("view2"), 7UL); LOG_INFO(logger, "over jumps fox {} {} {} {} {}", "example3", std::string("str1"), static_cast(9), std::string_view("view2"), 2); LOG_INFO(logger, "quick brown example {} {} {} {} {} {} {}", "example1", std::string_view("view2"), true, "example2", false, 3.0, static_cast(10)); LOG_INFO(logger, "test dog lazy {} {} {} {} {} {} {}", 5L, std::string("str1"), 8ULL, 2, "example2", true, false); LOG_INFO(logger, "brown lazy example {} {} {}", "example3", "example1", std::string_view("view2")); LOG_INFO(logger, "test logging brown {} {} {} {} {} {} {} {}", 5L, 8ULL, false, "example1", "example3", 1, static_cast(9), std::string_view("view1")); LOG_INFO(logger, "fox lazy over {} {} {} {} {} {} {}", 3.0, 5L, std::string_view("view2"), 2, static_cast(10), static_cast(9), 7UL); LOG_INFO(logger, "logging jumps over {} {} {} {}", "example2", 4.0f, 5L, std::string_view("view2")); LOG_INFO(logger, "jumps lazy quick brown {} {} {} {} {} {} {} {} {}", "example2", 4.0f, "example3", static_cast(9), 2, 7UL, 5L, std::string("str1"), std::string_view("view1")); LOG_INFO(logger, "jumps example lazy dog {} {} {} {} {}", static_cast(9), std::string("str2"), 3.0, static_cast(10), false); LOG_INFO(logger, "lazy over example {} {} {} {} {}", 2, "example1", static_cast(10), std::string("str2"), "example2"); LOG_INFO(logger, "quick logging brown fox {} {}", std::string("str1"), 7UL); LOG_INFO(logger, "over test brown quick {}", true); LOG_INFO(logger, "lazy over dog brown {} {} {} {} {}", 2, 1, "example2", true, "example1"); LOG_INFO(logger, "dog test fox {} {} {} {} {} {} {} {} {} {}", static_cast(10), false, std::string_view("view2"), std::string_view("view1"), 2, "example1", static_cast(9), "example3", "example2", std::string("str2")); LOG_INFO(logger, "over dog quick {} {} {} {} {} {}", "example2", 5L, static_cast(9), 1, true, 3.0); LOG_INFO(logger, "logging jumps example fox {} {} {} {} {} {}", std::string("str2"), 2, false, "example3", "example1", static_cast(9)); LOG_INFO(logger, "jumps dog example {}", std::string("str1")); LOG_INFO(logger, "over logging fox {} {} {} {} {} {} {} {}", "example3", std::string_view("view2"), 4.0f, false, 1, std::string("str2"), 5L, std::string_view("view1")); LOG_INFO(logger, "over brown fox lazy {} {} {} {} {}", true, 8ULL, "example2", std::string_view("view2"), static_cast(9)); LOG_INFO(logger, "fox lazy over {} {} {} {} {} {} {} {} {} {}", "example3", std::string("str1"), false, "example1", 1, "example2", 5L, std::string_view("view1"), static_cast(10), 6LL); LOG_INFO(logger, "example dog brown {} {} {} {} {} {} {} {}", true, "example1", std::string_view("view1"), std::string_view("view2"), "example2", 5L, static_cast(10), false); LOG_INFO(logger, "jumps dog test over {} {} {} {} {}", std::string("str2"), "example2", 2, 3.0, std::string_view("view1")); LOG_INFO(logger, "test over brown dog {} {} {} {} {} {}", std::string("str1"), 5L, false, static_cast(9), std::string("str2"), std::string_view("view2")); LOG_INFO(logger, "jumps example dog logging {} {}", "example3", true); LOG_INFO(logger, "dog quick jumps {} {} {} {}", 3.0, static_cast(9), false, 4.0f); LOG_INFO(logger, "dog over example logging {} {}", 4.0f, std::string("str1")); LOG_INFO(logger, "brown fox logging {} {} {} {} {} {} {}", false, 5L, 7UL, std::string_view("view1"), static_cast(9), static_cast(10), "example3"); LOG_INFO(logger, "brown fox quick dog {} {} {} {} {} {} {}", 4.0f, true, "example2", std::string_view("view1"), 3.0, 7UL, 6LL); LOG_INFO(logger, "lazy dog quick test {} {} {} {} {}", static_cast(9), std::string("str1"), "example1", 2, std::string_view("view2")); LOG_INFO(logger, "logging example dog {} {} {} {} {} {}", 7UL, static_cast(9), false, 1, 2, "example2"); LOG_INFO(logger, "jumps dog example test {} {} {} {} {} {}", 6LL, 4.0f, 7UL, "example1", false, std::string("str1")); LOG_INFO(logger, "jumps brown example over {} {} {}", 5L, 8ULL, static_cast(10)); LOG_INFO(logger, "logging fox dog {} {} {} {} {} {}", true, 6LL, 3.0, 1, false, 8ULL); LOG_INFO(logger, "example logging brown {} {}", static_cast(10), 5L); LOG_INFO(logger, "jumps example test quick {} {} {} {} {}", 5L, std::string("str1"), static_cast(10), 1, true); LOG_INFO(logger, "fox jumps example test {}", "example3"); LOG_INFO(logger, "over test quick dog {} {} {} {}", static_cast(10), 6LL, 8ULL, "example2"); LOG_INFO(logger, "quick example jumps dog {} {} {} {} {} {} {}", false, 7UL, 5L, static_cast(9), "example3", std::string("str1"), true); LOG_INFO(logger, "test logging jumps lazy {} {} {} {} {} {}", std::string_view("view1"), 7UL, 1, 2, "example1", false); LOG_INFO(logger, "example logging dog over {} {} {} {} {} {} {} {}", 1, 5L, "example2", static_cast(10), 3.0, std::string_view("view1"), false, 4.0f); LOG_INFO(logger, "test over lazy dog {} {} {} {} {} {} {} {} {}", std::string("str2"), "example1", true, 1, "example3", 5L, static_cast(10), std::string_view("view2"), 4.0f); LOG_INFO(logger, "quick lazy example brown {} {} {} {}", "example1", std::string("str2"), "example3", static_cast(10)); LOG_INFO(logger, "lazy example over {}", std::string("str2")); LOG_INFO(logger, "jumps over dog {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 1, "example3", 7UL, std::string("str2"), static_cast(9), "example2", std::string("str1"), 3.0, true); LOG_INFO(logger, "fox jumps brown {} {} {}", std::string_view("view1"), std::string("str1"), 5L); LOG_INFO(logger, "dog quick jumps logging {} {} {} {} {} {} {} {} {} {}", 6LL, std::string_view("view1"), true, 8ULL, false, std::string("str1"), 3.0, std::string("str2"), "example2", std::string_view("view2")); LOG_INFO(logger, "example fox lazy logging {} {} {} {} {} {}", "example1", true, std::string("str2"), 6LL, std::string_view("view2"), 4.0f); LOG_INFO(logger, "over fox jumps brown {} {} {} {} {} {}", static_cast(9), true, false, 5L, std::string_view("view2"), 6LL); LOG_INFO(logger, "dog logging over lazy {} {}", "example3", 5L); LOG_INFO(logger, "example test lazy brown {} {} {} {} {} {} {} {} {}", 8ULL, std::string_view("view2"), "example1", "example3", static_cast(9), 3.0, std::string("str1"), 5L, 7UL); LOG_INFO(logger, "logging quick over dog {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 7UL, "example1", false, static_cast(9), true, "example2", 5L, std::string_view("view1")); LOG_INFO(logger, "test logging lazy fox {} {} {} {} {} {} {} {}", 6LL, 7UL, 2, "example2", std::string("str2"), "example1", 5L, "example3"); LOG_INFO(logger, "quick brown lazy {} {} {} {}", static_cast(9), static_cast(10), 8ULL, 7UL); LOG_INFO(logger, "quick logging lazy dog {} {} {}", static_cast(9), "example1", static_cast(10)); LOG_INFO(logger, "brown lazy logging {}", std::string("str1")); LOG_INFO(logger, "fox example lazy test {} {} {} {} {} {} {}", 8ULL, true, "example3", static_cast(10), false, static_cast(9), 3.0); LOG_INFO(logger, "over fox lazy {} {} {} {} {} {} {} {}", std::string("str2"), std::string("str1"), 5L, "example3", "example2", std::string_view("view2"), static_cast(10), std::string_view("view1")); LOG_INFO(logger, "lazy example dog {} {} {} {} {}", 2, 1, 8ULL, 7UL, 4.0f); LOG_INFO(logger, "over test quick {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 6LL, 1, std::string("str1"), 4.0f, "example2", static_cast(10), 2, "example1", 3.0); LOG_INFO(logger, "brown test logging jumps {} {} {} {}", 2, 3.0, false, 5L); LOG_INFO(logger, "over lazy dog logging {} {} {} {} {} {} {} {} {}", 2, 8ULL, 4.0f, 7UL, std::string_view("view2"), static_cast(9), 3.0, "example2", std::string_view("view1")); LOG_INFO(logger, "dog test jumps {} {}", 6LL, static_cast(9)); LOG_INFO(logger, "test fox example {} {} {} {}", true, 1, 6LL, std::string("str1")); LOG_INFO(logger, "jumps logging quick example {} {} {} {} {} {}", std::string_view("view2"), 2, 8ULL, std::string("str2"), std::string("str1"), static_cast(9)); LOG_INFO(logger, "over logging dog {} {} {} {} {} {} {}", true, "example3", static_cast(10), 3.0, "example2", std::string("str1"), 8ULL); LOG_INFO(logger, "fox brown logging {} {} {} {} {} {} {} {}", "example2", 2, 6LL, "example3", std::string_view("view1"), std::string_view("view2"), false, 7UL); LOG_INFO(logger, "fox test over quick {} {}", std::string("str1"), 5L); LOG_INFO(logger, "quick over brown {} {} {} {} {} {} {}", 8ULL, std::string("str2"), false, 2, 4.0f, std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "over fox lazy logging {} {} {} {} {} {} {}", 1, 5L, std::string_view("view1"), 6LL, 4.0f, "example3", "example2"); LOG_INFO(logger, "quick over example {} {} {} {} {} {} {} {}", std::string_view("view2"), "example1", false, true, std::string_view("view1"), 2, 6LL, 4.0f); LOG_INFO(logger, "fox dog brown lazy {} {} {} {}", "example2", true, std::string("str2"), 3.0); LOG_INFO(logger, "jumps dog test quick {} {}", 8ULL, std::string_view("view2")); LOG_INFO(logger, "lazy quick fox jumps {} {} {} {} {} {} {}", std::string_view("view2"), static_cast(10), 3.0, static_cast(9), 8ULL, 7UL, "example2"); LOG_INFO(logger, "quick example dog {} {} {} {} {} {} {} {} {}", std::string("str2"), false, 2, 6LL, std::string_view("view2"), std::string_view("view1"), 5L, 7UL, std::string("str1")); LOG_INFO(logger, "over example lazy {} {} {} {} {} {} {}", 2, 8ULL, 5L, std::string_view("view2"), "example2", false, std::string("str2")); LOG_INFO(logger, "over jumps lazy test {} {} {} {}", true, std::string("str1"), static_cast(10), std::string("str2")); LOG_INFO(logger, "lazy dog quick {}", std::string_view("view1")); LOG_INFO(logger, "quick brown over {} {} {} {}", 4.0f, 1, std::string_view("view1"), "example2"); LOG_INFO(logger, "example quick jumps {} {} {} {}", 7UL, 4.0f, "example3", static_cast(9)); LOG_INFO(logger, "jumps dog over {} {} {} {} {} {} {} {} {}", 2, 8ULL, 5L, 4.0f, std::string_view("view2"), true, 7UL, 3.0, false); LOG_INFO(logger, "fox lazy example dog {}", std::string("str2")); LOG_INFO(logger, "logging over jumps {} {} {} {} {}", static_cast(10), "example3", std::string_view("view2"), 7UL, true); LOG_INFO(logger, "brown test jumps lazy {} {} {} {} {}", 6LL, 7UL, 2, std::string_view("view1"), 4.0f); LOG_INFO(logger, "over fox lazy dog {} {} {} {}", "example3", 1, 3.0, static_cast(9)); LOG_INFO(logger, "jumps dog lazy logging {} {} {} {} {} {} {} {} {}", std::string("str1"), false, "example3", 5L, std::string_view("view2"), std::string_view("view1"), 2, static_cast(9), true); LOG_INFO(logger, "fox over lazy {} {} {} {} {} {} {} {}", 2, 4.0f, std::string("str2"), "example3", 3.0, 1, 8ULL, "example2"); LOG_INFO(logger, "logging lazy jumps {} {} {} {} {}", static_cast(9), 4.0f, 5L, 6LL, std::string_view("view2")); LOG_INFO(logger, "lazy logging fox {} {} {} {} {} {} {} {}", 4.0f, 6LL, static_cast(9), 2, std::string("str1"), "example1", std::string_view("view1"), 1); LOG_INFO(logger, "over brown quick lazy {} {} {} {} {} {} {} {}", 5L, 8ULL, true, 7UL, "example1", std::string("str1"), static_cast(10), 1); LOG_INFO(logger, "logging brown quick {} {} {} {} {} {} {} {}", 8ULL, false, "example2", true, "example1", std::string_view("view1"), std::string_view("view2"), 7UL); LOG_INFO(logger, "example logging brown {} {} {} {} {}", 7UL, false, static_cast(10), true, 5L); LOG_INFO(logger, "lazy test jumps logging {} {} {} {} {} {}", static_cast(9), true, std::string("str1"), std::string_view("view2"), std::string_view("view1"), "example1"); LOG_INFO(logger, "test logging dog over {} {} {} {}", false, static_cast(9), 3.0, true); LOG_INFO(logger, "jumps over quick {} {} {} {} {}", 6LL, 3.0, std::string_view("view1"), std::string_view("view2"), 7UL); LOG_INFO(logger, "logging test quick {} {} {} {} {} {} {} {} {} {}", static_cast(10), 6LL, std::string("str1"), static_cast(9), "example2", true, 5L, std::string("str2"), 3.0, 2); LOG_INFO(logger, "jumps lazy test over {} {} {} {}", false, 6LL, 8ULL, std::string("str2")); LOG_INFO(logger, "brown example fox {} {}", std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "jumps brown example quick {} {} {} {}", 7UL, 2, 1, std::string_view("view2")); LOG_INFO(logger, "over example lazy {}", "example3"); LOG_INFO(logger, "test jumps lazy over {} {} {} {} {} {} {}", 5L, "example3", std::string_view("view1"), false, 2, std::string("str1"), 6LL); LOG_INFO(logger, "logging over test brown {} {} {} {} {} {} {} {} {} {}", 8ULL, 1, std::string("str2"), true, std::string("str1"), "example3", static_cast(9), std::string_view("view1"), std::string_view("view2"), "example1"); LOG_INFO(logger, "brown over test quick {} {} {} {} {} {} {} {} {} {}", 2, 7UL, std::string_view("view1"), 1, true, false, 6LL, 5L, "example1", 8ULL); LOG_INFO(logger, "lazy over jumps example {} {} {} {} {} {} {}", std::string_view("view2"), 3.0, "example3", "example2", "example1", 6LL, 2); LOG_INFO(logger, "test brown dog {} {} {} {} {} {} {} {} {} {}", static_cast(9), 2, std::string_view("view1"), std::string("str1"), 7UL, std::string_view("view2"), static_cast(10), "example1", "example2", 6LL); LOG_INFO(logger, "dog fox logging quick {} {}", 5L, static_cast(9)); LOG_INFO(logger, "jumps test quick {} {} {} {} {} {} {}", 8ULL, true, 2, std::string_view("view2"), "example1", 1, 6LL); LOG_INFO(logger, "lazy example quick logging {} {} {} {} {} {} {} {}", 1, std::string_view("view2"), "example3", std::string("str1"), static_cast(9), static_cast(10), 7UL, 4.0f); LOG_INFO(logger, "logging quick dog {} {} {}", "example2", std::string("str2"), 7UL); LOG_INFO(logger, "jumps over quick {} {} {} {} {} {} {}", 4.0f, std::string("str2"), 6LL, false, "example1", 5L, 8ULL); LOG_INFO(logger, "quick test brown {} {} {} {} {} {} {}", 7UL, false, 1, 4.0f, "example3", 5L, 8ULL); LOG_INFO(logger, "over fox example {}", std::string("str2")); LOG_INFO(logger, "fox logging lazy {} {}", 5L, "example2"); LOG_INFO(logger, "lazy brown quick over {} {} {} {} {} {} {} {} {} {}", static_cast(9), std::string("str1"), 4.0f, true, 7UL, 2, "example2", 5L, false, 1); LOG_INFO(logger, "quick dog over fox {} {} {}", false, "example2", std::string_view("view1")); LOG_INFO(logger, "over dog quick {} {} {} {}", std::string_view("view2"), static_cast(10), 6LL, std::string("str1")); LOG_INFO(logger, "dog over quick fox {} {}", "example2", "example1"); LOG_INFO(logger, "lazy fox quick {} {} {} {} {} {}", true, 2, std::string("str1"), std::string("str2"), static_cast(10), "example1"); LOG_INFO(logger, "lazy dog fox {}", "example3"); LOG_INFO(logger, "over example jumps dog {} {} {} {} {} {} {} {}", 4.0f, std::string("str2"), static_cast(10), 2, "example1", std::string_view("view2"), std::string("str1"), static_cast(9)); LOG_INFO(logger, "example quick test logging {} {} {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), false, 1, 7UL, 2, 8ULL, "example1", "example2"); LOG_INFO(logger, "brown test lazy {} {} {} {}", static_cast(9), 6LL, 2, 4.0f); LOG_INFO(logger, "dog example logging {} {} {} {} {} {} {} {} {}", "example3", std::string_view("view1"), 3.0, std::string_view("view2"), static_cast(10), true, 4.0f, 6LL, static_cast(9)); LOG_INFO(logger, "over jumps test quick {} {} {} {} {} {}", std::string_view("view2"), 7UL, 8ULL, std::string("str2"), 5L, "example1"); LOG_INFO(logger, "example brown fox {} {} {} {} {} {}", "example3", 4.0f, 7UL, 5L, 1, 2); LOG_INFO(logger, "dog test quick {}", std::string_view("view2")); LOG_INFO(logger, "example lazy quick {} {}", 3.0, static_cast(9)); LOG_INFO(logger, "dog test fox {} {} {} {} {} {} {} {} {} {}", false, true, 2, std::string("str1"), 6LL, "example2", std::string_view("view1"), std::string_view("view2"), std::string("str2"), 3.0); LOG_INFO(logger, "brown quick example {} {}", std::string("str2"), 6LL); LOG_INFO(logger, "dog brown quick {} {} {} {} {} {} {} {}", 1, 4.0f, 5L, true, 6LL, std::string("str1"), "example3", false); LOG_INFO(logger, "fox dog jumps quick {}", 8ULL); LOG_INFO(logger, "lazy jumps test {} {} {} {} {} {}", 1, "example1", static_cast(9), 3.0, false, 8ULL); LOG_INFO(logger, "fox logging example {} {} {} {} {} {} {} {} {}", "example2", 5L, 4.0f, 1, std::string_view("view1"), "example3", static_cast(9), true, 6LL); LOG_INFO(logger, "quick lazy brown {}", static_cast(9)); LOG_INFO(logger, "test logging lazy {} {} {} {}", static_cast(10), std::string_view("view2"), 4.0f, std::string_view("view1")); LOG_INFO(logger, "jumps dog over {} {}", false, 8ULL); LOG_INFO(logger, "quick test lazy {}", true); LOG_INFO(logger, "dog example logging lazy {} {} {}", 8ULL, std::string("str2"), "example2"); LOG_INFO(logger, "fox jumps dog over {} {} {} {} {} {}", 4.0f, "example3", 1, 8ULL, 2, true); LOG_INFO(logger, "lazy fox over quick {} {} {} {} {} {} {} {}", std::string_view("view2"), 2, 5L, static_cast(9), 3.0, 6LL, "example3", 4.0f); LOG_INFO(logger, "logging jumps fox lazy {} {} {} {} {}", std::string_view("view2"), false, static_cast(9), true, 8ULL); LOG_INFO(logger, "lazy fox quick {} {} {}", "example2", std::string_view("view1"), true); LOG_INFO(logger, "jumps dog lazy {} {} {}", static_cast(9), std::string("str2"), static_cast(10)); LOG_INFO(logger, "jumps quick logging test {} {} {} {} {} {} {}", static_cast(10), "example1", false, 4.0f, 8ULL, std::string_view("view1"), static_cast(9)); LOG_INFO(logger, "fox test jumps example {}", "example2"); LOG_INFO(logger, "example fox lazy quick {} {} {} {} {} {}", 8ULL, "example2", "example1", true, std::string_view("view2"), 6LL); LOG_INFO(logger, "test example over quick {} {} {} {}", 5L, "example2", false, 4.0f); LOG_INFO(logger, "over dog example {} {} {}", 6LL, std::string_view("view2"), std::string("str1")); LOG_INFO(logger, "jumps test fox logging {} {} {} {} {} {} {}", static_cast(10), 6LL, 7UL, std::string_view("view2"), static_cast(9), "example1", true); LOG_INFO(logger, "dog fox over {} {} {} {} {} {} {}", true, 7UL, static_cast(10), std::string("str1"), 3.0, std::string_view("view1"), 6LL); LOG_INFO(logger, "over fox dog {} {} {} {} {} {} {} {} {} {}", 4.0f, "example3", true, static_cast(9), 5L, "example1", std::string("str2"), 3.0, "example2", static_cast(10)); LOG_INFO(logger, "dog example brown jumps {} {} {} {} {} {}", static_cast(9), 7UL, true, 3.0, std::string("str1"), 1); LOG_INFO(logger, "lazy quick logging over {} {} {} {} {} {}", std::string_view("view1"), std::string_view("view2"), "example3", std::string("str2"), 5L, static_cast(9)); LOG_INFO(logger, "jumps test quick lazy {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), std::string_view("view1"), 3.0, 2, 4.0f, static_cast(9), false, 5L, static_cast(10), "example1"); LOG_INFO(logger, "brown lazy fox jumps {} {} {} {} {} {} {} {} {}", 8ULL, std::string("str1"), "example1", true, std::string_view("view1"), false, 2, 7UL, 4.0f); LOG_INFO(logger, "example lazy logging fox {} {} {} {}", "example1", 3.0, "example2", 5L); LOG_INFO(logger, "fox lazy test brown {}", true); LOG_INFO(logger, "dog brown jumps {} {} {} {} {} {} {}", false, "example3", 2, 8ULL, "example1", 3.0, true); LOG_INFO(logger, "quick test logging dog {} {} {}", 3.0, false, "example1"); LOG_INFO(logger, "test quick jumps {} {} {} {} {} {} {}", "example3", std::string("str2"), 8ULL, std::string("str1"), std::string_view("view2"), true, static_cast(9)); LOG_INFO(logger, "fox brown jumps {} {}", false, 3.0); LOG_INFO(logger, "brown quick dog over {} {} {} {} {} {} {} {} {} {}", 2, static_cast(10), 1, "example1", std::string("str2"), true, std::string_view("view2"), 6LL, 8ULL, std::string_view("view1")); LOG_INFO(logger, "logging quick example {} {} {} {}", 5L, "example3", 4.0f, 1); LOG_INFO(logger, "dog brown quick {}", 8ULL); LOG_INFO(logger, "lazy brown test {} {} {} {} {} {} {} {}", std::string("str1"), "example1", true, 6LL, 5L, 1, "example3", 8ULL); LOG_INFO(logger, "test example logging {} {}", 1, true); LOG_INFO(logger, "test jumps quick fox {} {} {} {} {} {} {} {} {}", "example1", 5L, 4.0f, false, 8ULL, 7UL, static_cast(10), 6LL, "example3"); LOG_INFO(logger, "lazy dog logging {} {} {}", "example3", std::string("str2"), 1); LOG_INFO(logger, "over example dog quick {}", "example3"); LOG_INFO(logger, "test quick lazy logging {} {} {} {} {} {} {}", std::string_view("view1"), 5L, "example3", 7UL, 3.0, true, 8ULL); LOG_INFO(logger, "test dog lazy {} {} {} {}", static_cast(10), 2, std::string_view("view2"), static_cast(9)); LOG_INFO(logger, "dog example jumps brown {} {} {}", "example3", 7UL, static_cast(10)); LOG_INFO(logger, "brown fox over dog {} {} {} {}", static_cast(10), "example2", 2, std::string_view("view1")); LOG_INFO(logger, "test example quick logging {} {} {} {} {} {} {} {} {} {}", "example3", "example1", 8ULL, std::string_view("view2"), false, true, 6LL, std::string("str2"), 5L, 7UL); LOG_INFO(logger, "over example dog fox {} {} {} {} {} {} {} {} {} {}", 3.0, "example3", true, 4.0f, false, 8ULL, std::string("str2"), static_cast(9), 6LL, 1); LOG_INFO(logger, "example logging over dog {} {} {} {} {} {} {}", 6LL, std::string_view("view2"), std::string("str1"), "example3", 1, std::string_view("view1"), 5L); LOG_INFO(logger, "brown jumps logging quick {} {} {}", 2, 1, static_cast(9)); LOG_INFO(logger, "dog test jumps {} {} {}", 6LL, 1, 3.0); LOG_INFO(logger, "brown test dog quick {} {} {} {} {} {}", "example3", 1, static_cast(9), std::string_view("view1"), 8ULL, std::string_view("view2")); LOG_INFO(logger, "quick jumps example dog {} {} {} {} {}", 2, std::string_view("view1"), 3.0, static_cast(10), 5L); LOG_INFO(logger, "logging brown quick {} {} {}", 5L, 1, 4.0f); LOG_INFO(logger, "logging jumps test brown {} {}", "example3", 6LL); LOG_INFO(logger, "brown over example {}", 6LL); LOG_INFO(logger, "fox dog example logging {} {} {} {} {} {} {} {}", false, static_cast(9), "example3", "example2", std::string("str2"), 8ULL, "example1", true); LOG_INFO(logger, "logging test over brown {}", 4.0f); LOG_INFO(logger, "over brown dog {} {} {} {} {} {} {} {} {} {}", 7UL, 4.0f, 2, std::string_view("view1"), 3.0, 5L, 6LL, 8ULL, "example3", 1); LOG_INFO(logger, "quick dog test {} {} {} {} {} {} {} {}", std::string_view("view1"), 6LL, 4.0f, "example2", "example1", 1, 7UL, 3.0); LOG_INFO(logger, "quick fox example test {} {} {} {} {} {}", "example3", static_cast(10), 2, 4.0f, 8ULL, std::string_view("view2")); LOG_INFO(logger, "jumps dog logging fox {} {} {} {} {}", std::string("str2"), static_cast(10), "example3", 6LL, std::string("str1")); LOG_INFO(logger, "lazy brown logging quick {} {} {} {} {}", static_cast(9), 8ULL, true, static_cast(10), 1); LOG_INFO(logger, "dog example jumps over {} {} {} {}", 2, 5L, 7UL, "example2"); LOG_INFO(logger, "example logging fox {} {} {} {} {} {} {} {} {}", 8ULL, true, static_cast(9), std::string("str1"), 4.0f, false, static_cast(10), 7UL, "example1"); LOG_INFO(logger, "lazy over quick {} {} {} {} {} {} {}", false, "example2", 3.0, std::string_view("view1"), std::string("str1"), 5L, 4.0f); LOG_INFO(logger, "fox brown jumps {} {} {} {}", std::string("str1"), 4.0f, 5L, std::string("str2")); LOG_INFO(logger, "logging test lazy {} {} {} {} {} {} {} {} {}", 8ULL, std::string("str1"), std::string("str2"), std::string_view("view2"), 2, 5L, 1, 7UL, 4.0f); LOG_INFO(logger, "brown example test {} {} {} {} {} {}", 4.0f, std::string_view("view2"), 2, std::string("str2"), static_cast(10), static_cast(9)); LOG_INFO(logger, "logging over test dog {} {}", "example2", static_cast(10)); LOG_INFO(logger, "brown example over {} {} {} {} {}", static_cast(9), std::string_view("view1"), false, true, 8ULL); LOG_INFO(logger, "logging brown quick {} {} {} {} {}", "example2", 7UL, 8ULL, 6LL, 3.0); LOG_INFO(logger, "example jumps dog {} {} {} {} {}", std::string_view("view2"), 7UL, 6LL, true, 5L); LOG_INFO(logger, "test lazy example {} {} {} {} {} {} {}", std::string_view("view1"), 5L, true, std::string("str2"), 7UL, static_cast(10), static_cast(9)); LOG_INFO(logger, "over dog jumps {} {}", static_cast(9), 8ULL); LOG_INFO(logger, "over test jumps {} {} {} {} {} {}", 5L, 1, std::string("str1"), "example3", std::string("str2"), 4.0f); LOG_INFO(logger, "brown dog logging {} {} {} {} {} {}", 3.0, 8ULL, "example2", 5L, std::string_view("view2"), "example1"); LOG_INFO(logger, "jumps dog example {} {} {} {} {}", "example2", 2, std::string("str2"), "example3", 5L); LOG_INFO(logger, "jumps dog logging fox {} {} {} {}", std::string("str1"), 3.0, false, std::string("str2")); LOG_INFO(logger, "fox dog quick jumps {} {} {} {} {} {} {} {} {} {}", 2, "example1", 4.0f, 3.0, 5L, "example3", true, "example2", 6LL, 7UL); LOG_INFO(logger, "dog example test quick {} {} {} {} {} {} {} {} {} {}", std::string("str1"), "example1", 5L, 4.0f, 8ULL, true, 7UL, std::string_view("view2"), std::string("str2"), static_cast(10)); LOG_INFO(logger, "quick jumps dog {} {} {} {} {} {} {} {} {}", "example3", "example2", static_cast(10), 4.0f, true, std::string_view("view1"), 1, 2, 6LL); LOG_INFO(logger, "example jumps over logging {} {} {} {} {} {} {}", 1, false, static_cast(9), std::string_view("view2"), "example2", 7UL, std::string("str2")); LOG_INFO(logger, "lazy over fox dog {} {} {} {} {} {} {} {}", 8ULL, 1, std::string("str1"), 2, 4.0f, 3.0, static_cast(10), "example1"); LOG_INFO(logger, "brown over quick example {} {} {} {} {} {} {} {}", false, 3.0, 4.0f, "example3", std::string_view("view2"), 7UL, std::string("str2"), true); LOG_INFO(logger, "fox logging test over {} {} {} {} {} {} {} {}", 7UL, 8ULL, static_cast(10), 5L, "example1", 2, true, std::string_view("view2")); LOG_INFO(logger, "brown example logging {} {} {} {} {} {}", true, std::string("str2"), 3.0, "example1", std::string_view("view2"), 6LL); LOG_INFO(logger, "brown lazy quick {} {} {} {} {} {} {} {} {}", true, 4.0f, std::string_view("view1"), static_cast(10), 3.0, 8ULL, std::string("str2"), 6LL, std::string_view("view2")); LOG_INFO(logger, "brown over example {} {} {} {} {} {} {}", std::string_view("view2"), "example3", static_cast(10), 5L, std::string("str2"), static_cast(9), 1); LOG_INFO(logger, "jumps dog logging test {} {} {} {} {}", 3.0, std::string("str1"), "example1", "example3", static_cast(9)); LOG_INFO(logger, "jumps fox test quick {}", "example3"); LOG_INFO(logger, "quick dog logging lazy {} {} {} {} {}", 8ULL, "example2", static_cast(9), 4.0f, 5L); LOG_INFO(logger, "test example over {} {} {} {} {}", 7UL, std::string("str1"), 1, 8ULL, std::string_view("view2")); LOG_INFO(logger, "quick lazy brown {} {}", 8ULL, 6LL); LOG_INFO(logger, "test brown fox {}", 1); LOG_INFO(logger, "over example lazy {} {} {} {} {} {}", 2, 6LL, 1, 4.0f, std::string("str1"), std::string_view("view1")); LOG_INFO(logger, "fox test jumps {} {} {} {} {} {} {}", "example3", true, "example1", std::string_view("view2"), 7UL, 5L, std::string("str1")); LOG_INFO(logger, "logging lazy example {} {}", std::string_view("view2"), std::string_view("view1")); LOG_INFO(logger, "logging fox dog {} {} {}", std::string("str2"), true, std::string_view("view2")); LOG_INFO(logger, "jumps over brown {} {} {}", 4.0f, "example1", std::string_view("view1")); LOG_INFO(logger, "over lazy dog brown {} {} {} {} {} {} {} {} {}", false, std::string_view("view2"), std::string_view("view1"), 1, std::string("str1"), "example3", 3.0, "example1", 4.0f); LOG_INFO(logger, "dog test brown lazy {} {} {} {} {} {} {}", std::string("str2"), true, "example1", 2, std::string_view("view2"), "example3", 7UL); LOG_INFO(logger, "example lazy quick dog {} {}", 4.0f, static_cast(10)); LOG_INFO(logger, "test brown lazy dog {}", 5L); LOG_INFO(logger, "quick fox logging {} {} {} {} {} {}", std::string_view("view2"), "example1", std::string_view("view1"), 8ULL, "example3", static_cast(10)); LOG_INFO(logger, "over dog quick fox {} {} {} {} {} {} {} {} {} {}", false, 3.0, std::string_view("view1"), "example1", 1, static_cast(10), 2, static_cast(9), 6LL, 4.0f); LOG_INFO(logger, "jumps example brown {} {} {} {} {}", true, 1, std::string("str2"), static_cast(9), 6LL); LOG_INFO(logger, "over test logging quick {} {} {} {} {} {} {} {}", 4.0f, "example2", std::string_view("view1"), 8ULL, 3.0, 5L, "example1", 2); LOG_INFO(logger, "lazy dog test jumps {} {} {} {} {} {} {} {} {} {}", static_cast(10), 6LL, 4.0f, 7UL, false, std::string_view("view2"), 3.0, "example2", 1, true); LOG_INFO(logger, "example dog fox brown {} {} {} {} {}", std::string("str1"), false, 3.0, 8ULL, true); LOG_INFO(logger, "jumps over logging test {} {}", 1, std::string("str1")); LOG_INFO(logger, "dog test brown {}", 4.0f); LOG_INFO(logger, "over dog test example {} {} {} {}", std::string("str1"), 8ULL, 5L, 2); LOG_INFO(logger, "quick test lazy logging {} {} {} {} {} {} {} {} {} {}", "example1", "example2", 2, std::string_view("view1"), std::string("str2"), false, 1, static_cast(9), std::string_view("view2"), std::string("str1")); LOG_INFO(logger, "example test fox over {} {} {} {} {} {} {}", 3.0, 6LL, std::string("str2"), static_cast(9), std::string("str1"), 4.0f, 1); LOG_INFO(logger, "test jumps logging {} {} {} {} {} {}", 3.0, 5L, std::string("str1"), std::string("str2"), static_cast(9), 1); LOG_INFO(logger, "dog example fox logging {} {} {} {} {} {} {}", std::string("str2"), 3.0, 7UL, 5L, std::string_view("view2"), 8ULL, 1); LOG_INFO(logger, "over fox lazy {} {} {} {} {} {}", 1, 6LL, 2, std::string("str1"), "example1", false); LOG_INFO(logger, "logging test lazy dog {} {} {} {} {} {} {} {} {} {}", static_cast(10), 8ULL, false, std::string("str1"), std::string_view("view2"), "example1", std::string_view("view1"), 2, 1, 5L); LOG_INFO(logger, "quick dog jumps {} {} {}", static_cast(9), std::string("str2"), 8ULL); LOG_INFO(logger, "fox test dog over {} {} {} {} {} {} {}", 4.0f, true, false, 3.0, 7UL, 8ULL, "example3"); LOG_INFO(logger, "jumps over logging quick {}", static_cast(10)); LOG_INFO(logger, "jumps logging fox example {} {} {} {} {} {} {} {} {} {}", "example3", "example1", static_cast(10), std::string("str2"), 8ULL, static_cast(9), 4.0f, std::string("str1"), std::string_view("view2"), 7UL); LOG_INFO(logger, "fox over quick test {}", false); LOG_INFO(logger, "brown dog quick test {} {} {} {} {} {} {}", std::string("str2"), std::string("str1"), static_cast(9), true, false, "example1", 3.0); LOG_INFO(logger, "over example brown {} {} {} {} {} {} {} {}", 7UL, 8ULL, "example3", static_cast(9), "example1", std::string("str1"), std::string_view("view1"), true); LOG_INFO(logger, "jumps test example {}", 8ULL); LOG_INFO(logger, "over test example brown {} {} {} {} {} {} {} {} {}", true, 4.0f, std::string_view("view1"), "example3", std::string("str2"), 3.0, static_cast(9), 1, static_cast(10)); LOG_INFO(logger, "logging jumps test example {} {} {} {} {}", 7UL, "example2", 1, 2, 5L); LOG_INFO(logger, "lazy jumps brown {} {}", "example2", std::string_view("view2")); LOG_INFO(logger, "brown over quick {} {} {} {} {} {} {}", std::string_view("view1"), 5L, static_cast(10), std::string_view("view2"), "example1", 4.0f, 2); LOG_INFO(logger, "test example fox over {} {} {} {} {}", 4.0f, false, "example2", true, 8ULL); LOG_INFO(logger, "quick fox lazy over {} {} {} {} {} {}", std::string("str1"), static_cast(9), 5L, static_cast(10), std::string_view("view2"), 8ULL); LOG_INFO(logger, "test logging lazy {} {} {}", "example1", 7UL, 1); LOG_INFO(logger, "fox dog example {} {} {} {} {} {}", "example3", std::string_view("view2"), 8ULL, false, std::string("str2"), "example2"); LOG_INFO(logger, "over fox dog example {} {} {} {} {} {}", std::string_view("view1"), "example3", "example2", 2, "example1", 6LL); LOG_INFO(logger, "dog brown example quick {} {} {} {} {} {} {} {} {} {}", 3.0, "example3", 2, 8ULL, 4.0f, std::string_view("view1"), 5L, 7UL, static_cast(10), "example2"); LOG_INFO(logger, "test fox dog jumps {} {} {} {} {}", "example1", static_cast(10), "example3", 7UL, 1); LOG_INFO(logger, "fox dog over {} {} {} {} {}", std::string("str1"), static_cast(10), 4.0f, 2, static_cast(9)); LOG_INFO(logger, "logging brown fox {}", 3.0); LOG_INFO(logger, "example fox over brown {} {} {}", 3.0, "example3", 1); LOG_INFO(logger, "quick dog lazy jumps {} {} {} {} {} {} {} {} {} {}", 8ULL, "example2", "example3", 1, 5L, false, 3.0, std::string_view("view2"), "example1", true); LOG_INFO(logger, "jumps dog test {} {} {} {} {} {} {} {} {} {}", 5L, 2, "example1", 1, 7UL, false, "example2", static_cast(10), true, std::string("str1")); LOG_INFO(logger, "quick logging lazy example {} {}", false, "example3"); LOG_INFO(logger, "example logging test {} {} {} {} {} {} {} {} {} {}", 6LL, 1, std::string("str1"), "example2", 3.0, 8ULL, "example1", 5L, 2, "example3"); LOG_INFO(logger, "example jumps dog quick {} {} {} {} {} {} {}", 7UL, static_cast(10), 6LL, "example1", std::string_view("view2"), std::string("str1"), std::string("str2")); LOG_INFO(logger, "quick logging jumps example {} {}", "example3", static_cast(10)); LOG_INFO(logger, "dog example lazy test {} {} {} {} {}", std::string("str2"), std::string_view("view1"), 6LL, static_cast(9), static_cast(10)); LOG_INFO(logger, "lazy logging jumps dog {} {} {} {} {} {} {} {} {}", 1, "example2", std::string_view("view2"), true, static_cast(9), 5L, std::string("str1"), "example3", static_cast(10)); LOG_INFO(logger, "logging jumps dog lazy {} {} {} {} {} {} {} {} {}", false, std::string("str1"), std::string_view("view2"), "example2", 2, static_cast(9), std::string_view("view1"), 6LL, 7UL); LOG_INFO(logger, "test lazy example {} {} {} {} {}", static_cast(9), true, std::string("str1"), 1, 2); LOG_INFO(logger, "quick lazy test {} {}", std::string("str2"), 8ULL); LOG_INFO(logger, "logging quick example dog {} {} {} {} {}", 1, 3.0, static_cast(9), 6LL, std::string("str2")); LOG_INFO(logger, "logging quick test {} {} {} {} {} {} {}", 8ULL, 7UL, static_cast(10), 1, "example3", 4.0f, "example1"); LOG_INFO(logger, "quick logging over jumps {} {}", 3.0, 1); LOG_INFO(logger, "over example brown jumps {}", 8ULL); LOG_INFO(logger, "dog jumps brown logging {} {} {} {} {} {} {} {}", "example2", std::string_view("view2"), std::string_view("view1"), 8ULL, static_cast(10), 5L, std::string("str2"), 7UL); LOG_INFO(logger, "test example brown jumps {} {} {}", 6LL, 5L, 8ULL); LOG_INFO(logger, "jumps example quick over {} {} {} {} {} {} {} {} {} {}", 5L, "example1", false, 3.0, "example3", std::string("str2"), 2, std::string("str1"), true, 4.0f); LOG_INFO(logger, "dog brown jumps lazy {} {} {} {} {} {} {} {} {} {}", 1, 3.0, static_cast(10), "example1", std::string("str2"), std::string_view("view1"), std::string_view("view2"), 4.0f, "example2", false); LOG_INFO(logger, "fox dog over {} {} {} {} {} {} {} {} {} {}", 5L, 6LL, true, "example3", static_cast(10), "example2", std::string("str1"), false, std::string("str2"), 8ULL); LOG_INFO(logger, "lazy jumps test dog {} {} {} {} {} {} {} {} {} {}", 5L, 8ULL, false, 7UL, 2, static_cast(9), "example2", static_cast(10), "example3", 6LL); LOG_INFO(logger, "over lazy example {} {} {}", std::string("str2"), "example2", std::string("str1")); LOG_INFO(logger, "fox dog example logging {} {} {} {} {}", std::string_view("view1"), "example1", 3.0, 7UL, 2); LOG_INFO(logger, "example logging lazy {} {} {} {} {} {}", 4.0f, true, "example3", std::string_view("view1"), std::string("str2"), std::string("str1")); LOG_INFO(logger, "lazy fox quick over {} {} {} {} {}", 1, 7UL, 4.0f, 3.0, 2); LOG_INFO(logger, "logging quick brown fox {} {} {} {} {} {} {} {} {} {}", false, std::string_view("view2"), std::string("str1"), std::string_view("view1"), 3.0, "example2", 4.0f, 7UL, static_cast(9), std::string("str2")); LOG_INFO(logger, "quick example fox {} {} {} {} {} {} {} {}", 5L, 8ULL, static_cast(10), false, std::string("str2"), "example2", 7UL, 6LL); LOG_INFO(logger, "logging fox example {} {} {} {} {} {} {} {}", 2, 8ULL, 4.0f, true, static_cast(10), 5L, 1, 6LL); LOG_INFO(logger, "over example fox test {} {} {} {} {} {}", 6LL, 7UL, std::string_view("view2"), 2, 3.0, true); LOG_INFO(logger, "lazy test brown {} {} {}", 8ULL, "example1", false); LOG_INFO(logger, "dog over jumps {} {} {}", std::string_view("view1"), 3.0, 6LL); LOG_INFO(logger, "over dog fox {} {} {} {} {}", std::string_view("view2"), "example2", false, static_cast(10), std::string("str1")); LOG_INFO(logger, "over dog jumps {} {} {} {} {} {} {} {}", 7UL, 2, true, std::string("str1"), static_cast(10), "example2", 3.0, 6LL); LOG_INFO(logger, "brown quick over {} {} {} {} {} {}", std::string_view("view1"), static_cast(10), 5L, 6LL, "example1", std::string_view("view2")); LOG_INFO(logger, "logging jumps example brown {} {}", static_cast(10), false); LOG_INFO(logger, "fox quick test brown {} {} {} {} {} {} {} {}", 7UL, static_cast(9), "example1", false, 6LL, std::string_view("view1"), std::string("str2"), static_cast(10)); LOG_INFO(logger, "jumps test brown lazy {} {} {} {} {}", 1, 2, std::string("str1"), static_cast(9), "example1"); LOG_INFO(logger, "logging test lazy {} {} {} {} {} {} {}", false, static_cast(9), 3.0, std::string("str1"), true, 6LL, static_cast(10)); LOG_INFO(logger, "dog logging fox lazy {} {} {} {} {} {}", 4.0f, 6LL, 1, 2, std::string("str1"), std::string_view("view2")); LOG_INFO(logger, "lazy dog logging test {} {} {} {} {}", "example1", 8ULL, std::string_view("view1"), 7UL, std::string_view("view2")); LOG_INFO(logger, "quick jumps dog over {} {} {} {} {} {}", 7UL, "example1", 2, false, true, 1); LOG_INFO(logger, "logging jumps lazy {} {} {} {} {} {} {} {}", std::string_view("view2"), 1, 2, std::string_view("view1"), "example3", "example2", 3.0, true); LOG_INFO(logger, "jumps example over {} {} {} {} {} {} {} {} {} {}", 1, std::string_view("view2"), std::string_view("view1"), 3.0, 8ULL, static_cast(10), "example1", false, std::string("str1"), 6LL); LOG_INFO(logger, "test quick example brown {}", "example3"); LOG_INFO(logger, "jumps over example lazy {} {} {} {} {}", static_cast(9), 5L, "example1", "example3", std::string("str2")); LOG_INFO(logger, "dog fox over {} {} {}", "example3", 3.0, "example1"); LOG_INFO(logger, "over logging jumps {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 8ULL, "example3", true, "example2", 3.0, std::string_view("view1"), std::string("str1"), false); LOG_INFO(logger, "dog lazy brown {} {} {} {} {} {} {}", "example1", std::string_view("view1"), static_cast(10), std::string("str1"), false, 3.0, true); LOG_INFO(logger, "logging quick fox {} {} {} {} {} {}", 7UL, 3.0, static_cast(10), 4.0f, "example1", std::string_view("view1")); LOG_INFO(logger, "lazy quick example jumps {} {} {} {} {} {}", static_cast(9), false, "example2", 7UL, 1, "example1"); LOG_INFO(logger, "quick brown example {} {}", 4.0f, 7UL); LOG_INFO(logger, "over brown logging {} {} {} {} {}", std::string_view("view2"), std::string_view("view1"), 7UL, 2, static_cast(10)); LOG_INFO(logger, "brown over jumps logging {} {} {} {} {} {} {} {} {} {}", true, std::string("str1"), 1, static_cast(9), false, 4.0f, static_cast(10), 2, 6LL, "example1"); LOG_INFO(logger, "jumps fox lazy test {} {} {} {} {} {} {} {} {} {}", 2, true, "example2", false, std::string("str1"), 5L, 4.0f, std::string_view("view2"), static_cast(9), 7UL); LOG_INFO(logger, "example fox test {} {} {} {} {} {}", false, 8ULL, std::string("str2"), true, 7UL, std::string_view("view1")); LOG_INFO(logger, "logging fox over {} {} {} {} {} {} {}", static_cast(10), 8ULL, std::string_view("view2"), 6LL, std::string("str1"), 4.0f, 3.0); LOG_INFO(logger, "test dog lazy {} {} {} {} {} {}", std::string_view("view1"), static_cast(9), std::string_view("view2"), 5L, false, 2); LOG_INFO(logger, "brown over quick {} {} {}", 8ULL, 7UL, false); LOG_INFO(logger, "lazy quick dog {} {} {} {} {}", "example1", "example2", "example3", std::string_view("view1"), 8ULL); LOG_INFO(logger, "over dog example {} {} {} {} {} {} {}", "example2", 6LL, false, "example1", 2, static_cast(10), 7UL); LOG_INFO(logger, "brown test jumps {} {} {}", 4.0f, true, 6LL); LOG_INFO(logger, "jumps over logging quick {} {} {} {} {} {} {}", 6LL, 7UL, static_cast(10), 3.0, 5L, 8ULL, 4.0f); LOG_INFO(logger, "lazy quick fox test {} {} {} {} {} {}", static_cast(10), 4.0f, std::string_view("view1"), 1, 2, true); LOG_INFO(logger, "test example dog {} {}", "example2", 1); LOG_INFO(logger, "fox over brown quick {} {} {} {} {} {} {} {} {} {}", 2, "example3", 8ULL, "example2", std::string("str1"), static_cast(10), std::string("str2"), static_cast(9), std::string_view("view2"), 4.0f); LOG_INFO(logger, "test dog quick fox {} {} {} {} {} {} {} {} {}", 5L, "example2", true, "example1", "example3", false, 4.0f, 3.0, std::string_view("view2")); LOG_INFO(logger, "example fox dog over {} {} {} {} {} {} {}", true, static_cast(9), std::string_view("view1"), 1, 5L, 4.0f, std::string("str2")); LOG_INFO(logger, "lazy brown fox over {}", std::string("str1")); LOG_INFO(logger, "test over dog logging {} {} {} {} {} {}", false, 8ULL, static_cast(10), 2, 4.0f, "example1"); LOG_INFO(logger, "brown fox over {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 8ULL, 6LL, false, "example3", 5L, std::string("str1"), "example2", "example1", 3.0); LOG_INFO(logger, "over test example {} {} {}", false, 8ULL, 3.0); LOG_INFO(logger, "example fox dog brown {} {} {} {} {} {} {}", std::string("str2"), "example1", 4.0f, 1, static_cast(10), 3.0, 6LL); LOG_INFO(logger, "brown fox lazy example {} {}", 4.0f, 2); LOG_INFO(logger, "over logging example {} {} {} {} {} {} {} {}", 2, std::string("str1"), "example1", 6LL, 3.0, std::string("str2"), "example2", true); LOG_INFO(logger, "dog logging test lazy {} {} {} {} {} {} {} {} {} {}", 1, std::string("str2"), "example1", "example3", std::string_view("view2"), std::string_view("view1"), static_cast(9), 4.0f, 7UL, 3.0); LOG_INFO(logger, "jumps over test {} {} {} {} {} {} {} {} {}", 3.0, 4.0f, static_cast(10), std::string("str1"), std::string("str2"), 5L, 7UL, true, false); LOG_INFO(logger, "over example quick brown {} {}", 6LL, true); LOG_INFO(logger, "logging over brown quick {} {} {}", "example2", static_cast(9), 7UL); LOG_INFO(logger, "logging brown test fox {} {} {} {} {} {} {} {} {}", true, 7UL, std::string("str1"), std::string_view("view2"), static_cast(10), 4.0f, std::string_view("view1"), "example3", false); LOG_INFO(logger, "example dog over {} {} {} {} {} {} {}", 2, 6LL, false, 7UL, static_cast(10), 1, std::string_view("view1")); LOG_INFO(logger, "over quick lazy test {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 1, 5L, "example3", std::string("str1"), static_cast(10), static_cast(9), 4.0f, 6LL); LOG_INFO(logger, "jumps over example {}", static_cast(10)); LOG_INFO(logger, "logging quick lazy {} {}", 4.0f, 8ULL); LOG_INFO(logger, "over test logging dog {}", 7UL); LOG_INFO(logger, "test jumps brown quick {} {} {} {} {}", std::string("str1"), static_cast(9), 3.0, std::string("str2"), std::string_view("view2")); LOG_INFO(logger, "test logging over {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), "example1", "example2", 2, false, "example3", 8ULL, 1, true, 7UL); LOG_INFO(logger, "lazy dog logging {} {} {} {} {} {} {} {} {} {}", std::string("str2"), 2, "example2", 4.0f, "example1", static_cast(10), std::string("str1"), 7UL, static_cast(9), std::string_view("view2")); LOG_INFO(logger, "jumps example quick {} {} {} {} {} {} {}", 8ULL, std::string("str1"), static_cast(10), false, static_cast(9), "example1", 4.0f); LOG_INFO(logger, "logging fox dog {} {} {} {} {} {} {} {} {}", 4.0f, "example1", 1, 7UL, true, std::string_view("view1"), false, static_cast(10), std::string_view("view2")); LOG_INFO(logger, "logging example dog test {} {} {} {} {}", false, static_cast(9), 7UL, static_cast(10), 8ULL); LOG_INFO(logger, "jumps brown test example {} {} {}", false, std::string_view("view2"), std::string("str2")); LOG_INFO(logger, "quick test lazy dog {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 6LL, 3.0, std::string("str2"), static_cast(10), 4.0f, 5L, true, false, "example3"); LOG_INFO(logger, "quick brown fox {} {} {} {} {} {} {} {} {}", 8ULL, "example1", false, "example2", 3.0, 4.0f, 6LL, true, 5L); LOG_INFO(logger, "test brown over {}", std::string_view("view1")); LOG_INFO(logger, "logging brown quick over {}", static_cast(10)); LOG_INFO(logger, "jumps lazy over {}", std::string_view("view2")); LOG_INFO(logger, "brown dog jumps over {} {} {}", std::string_view("view1"), 8ULL, "example3"); LOG_INFO(logger, "quick test dog fox {} {} {} {} {} {} {} {} {}", true, false, static_cast(9), std::string("str1"), "example1", 8ULL, std::string_view("view1"), 4.0f, std::string_view("view2")); LOG_INFO(logger, "test logging brown dog {} {} {} {} {} {} {} {} {} {}", 7UL, 6LL, 2, static_cast(10), 4.0f, std::string_view("view2"), 1, false, static_cast(9), "example2"); LOG_INFO(logger, "lazy fox brown quick {}", "example2"); LOG_INFO(logger, "dog fox example quick {} {} {} {} {}", static_cast(9), false, true, 3.0, std::string_view("view1")); LOG_INFO(logger, "over jumps example quick {} {} {} {} {} {} {} {} {} {}", static_cast(10), false, "example3", 1, 7UL, 2, true, 4.0f, "example1", static_cast(9)); LOG_INFO(logger, "fox dog brown {}", 8ULL); LOG_INFO(logger, "example fox dog {} {} {} {} {} {}", false, std::string_view("view2"), static_cast(9), std::string("str1"), "example3", "example2"); LOG_INFO(logger, "lazy test jumps {} {}", "example2", 6LL); LOG_INFO(logger, "logging example fox {} {} {} {} {} {} {} {}", static_cast(9), 3.0, "example3", 1, std::string_view("view1"), std::string("str1"), static_cast(10), "example2"); LOG_INFO(logger, "lazy over fox example {} {} {} {} {} {} {} {} {} {}", static_cast(9), 7UL, false, 3.0, 4.0f, std::string_view("view1"), "example2", std::string_view("view2"), "example1", 8ULL); LOG_INFO(logger, "quick lazy logging {} {} {} {} {} {} {}", false, std::string_view("view1"), "example1", true, "example3", std::string_view("view2"), static_cast(9)); LOG_INFO(logger, "dog lazy jumps {} {} {} {}", 3.0, std::string("str2"), 1, 6LL); LOG_INFO(logger, "dog example brown test {} {} {} {} {} {}", 6LL, 2, 8ULL, static_cast(10), "example2", 1); LOG_INFO(logger, "lazy jumps dog {} {} {} {} {} {} {} {} {} {}", 3.0, static_cast(9), 6LL, std::string_view("view2"), true, 5L, std::string("str2"), "example2", "example3", std::string_view("view1")); LOG_INFO(logger, "fox dog logging quick {} {}", "example1", "example2"); LOG_INFO(logger, "dog jumps example over {} {} {} {} {} {} {}", "example1", 2, 5L, 8ULL, std::string("str2"), 6LL, "example3"); LOG_INFO(logger, "dog lazy quick {} {} {} {} {} {} {} {} {}", 8ULL, std::string("str1"), "example3", 3.0, std::string_view("view1"), true, static_cast(9), 1, static_cast(10)); LOG_INFO(logger, "jumps brown lazy {} {} {} {} {} {} {}", std::string("str2"), 2, static_cast(10), true, "example3", std::string_view("view2"), 6LL); LOG_INFO(logger, "brown dog example {} {} {}", std::string("str2"), static_cast(10), true); LOG_INFO(logger, "fox brown lazy {} {} {} {} {} {}", 6LL, "example1", std::string("str1"), true, std::string("str2"), "example3"); LOG_INFO(logger, "quick over jumps logging {} {}", 4.0f, std::string("str1")); LOG_INFO(logger, "dog fox brown quick {} {} {} {} {} {} {} {} {}", "example2", std::string("str2"), 7UL, static_cast(10), 6LL, 8ULL, std::string_view("view2"), "example1", 4.0f); LOG_INFO(logger, "quick example dog {} {} {} {} {} {}", false, "example1", true, 5L, 3.0, static_cast(10)); LOG_INFO(logger, "test brown lazy dog {} {}", std::string("str2"), 2); LOG_INFO(logger, "dog logging example {} {} {} {} {} {} {} {} {}", 7UL, std::string("str1"), 8ULL, 6LL, 2, false, "example3", std::string_view("view1"), std::string("str2")); LOG_INFO(logger, "dog test quick {} {} {} {} {}", std::string_view("view2"), 2, static_cast(10), "example3", 8ULL); LOG_INFO(logger, "lazy example dog {}", static_cast(9)); LOG_INFO(logger, "example dog logging {} {} {} {} {} {} {} {}", 5L, 8ULL, 2, false, "example2", true, static_cast(9), 4.0f); LOG_INFO(logger, "test logging example brown {} {} {} {} {} {} {} {} {}", "example3", 4.0f, 5L, static_cast(9), 2, std::string_view("view1"), std::string_view("view2"), true, 6LL); LOG_INFO(logger, "over example brown {} {} {} {} {}", 1, "example2", std::string_view("view2"), std::string_view("view1"), "example3"); LOG_INFO(logger, "over example lazy quick {}", 8ULL); LOG_INFO(logger, "logging dog fox {} {} {} {} {} {} {} {}", static_cast(10), std::string_view("view2"), 8ULL, 1, "example3", static_cast(9), std::string("str2"), true); LOG_INFO(logger, "quick dog example {} {} {} {} {} {} {} {}", 1, 3.0, std::string("str2"), static_cast(9), std::string_view("view1"), static_cast(10), "example3", 4.0f); LOG_INFO(logger, "dog quick logging jumps {} {} {} {} {}", 2, std::string("str1"), "example2", 1, true); LOG_INFO(logger, "dog fox logging test {} {} {} {} {} {} {} {} {} {}", 1, static_cast(9), std::string_view("view2"), "example1", 3.0, 5L, true, 2, std::string_view("view1"), 8ULL); LOG_INFO(logger, "dog jumps fox quick {} {}", true, 2); LOG_INFO(logger, "jumps over dog quick {} {} {} {} {} {} {} {} {} {}", "example2", 6LL, 8ULL, 1, 4.0f, 7UL, 2, std::string_view("view1"), false, 5L); LOG_INFO(logger, "logging example quick lazy {} {} {} {} {} {} {} {} {} {}", "example3", 2, false, std::string("str1"), 1, "example2", std::string_view("view2"), 6LL, true, 7UL); LOG_INFO(logger, "fox quick jumps logging {} {} {} {} {} {} {} {} {} {}", static_cast(10), 1, std::string_view("view1"), static_cast(9), false, true, std::string("str2"), 3.0, 5L, std::string("str1")); LOG_INFO(logger, "fox dog brown {} {}", std::string("str1"), static_cast(10)); LOG_INFO(logger, "fox jumps lazy {} {} {} {}", std::string_view("view1"), "example3", false, std::string("str2")); LOG_INFO(logger, "brown lazy example fox {} {}", "example2", 1); LOG_INFO(logger, "quick lazy example jumps {} {}", true, std::string_view("view1")); LOG_INFO(logger, "test quick fox {} {} {} {}", 6LL, std::string("str1"), 8ULL, std::string("str2")); LOG_INFO(logger, "dog logging test lazy {}", std::string("str1")); LOG_INFO(logger, "lazy over dog example {} {} {} {} {} {} {}", 7UL, 8ULL, std::string_view("view1"), "example2", std::string("str2"), static_cast(10), 5L); LOG_INFO(logger, "example logging brown jumps {} {} {} {} {} {} {} {}", 5L, 6LL, std::string_view("view2"), std::string_view("view1"), 2, true, 7UL, std::string("str1")); LOG_INFO(logger, "fox brown lazy over {} {} {} {} {} {} {} {} {} {}", 2, "example1", 6LL, 4.0f, 5L, true, std::string_view("view2"), std::string_view("view1"), "example3", std::string("str2")); LOG_INFO(logger, "logging dog brown lazy {} {} {} {} {} {} {} {} {} {}", 4.0f, "example3", "example2", std::string_view("view2"), 5L, false, std::string("str2"), std::string_view("view1"), 7UL, std::string("str1")); LOG_INFO(logger, "test fox quick brown {} {} {} {} {} {} {} {} {}", false, static_cast(10), std::string("str1"), true, "example2", 2, 7UL, std::string_view("view1"), 4.0f); LOG_INFO(logger, "over brown jumps {} {} {} {} {} {} {} {} {}", 6LL, static_cast(9), false, "example3", 5L, 8ULL, 1, std::string("str1"), static_cast(10)); LOG_INFO(logger, "example brown dog lazy {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), false, static_cast(9), true, 1, 6LL, 8ULL, 7UL, 3.0, "example2"); LOG_INFO(logger, "lazy dog over {} {} {} {} {} {}", std::string("str2"), "example3", std::string_view("view1"), "example2", static_cast(9), static_cast(10)); LOG_INFO(logger, "fox example quick lazy {} {} {} {}", 8ULL, 2, static_cast(9), true); LOG_INFO(logger, "test over fox {} {} {} {} {} {} {}", false, "example2", "example1", 2, 1, "example3", 5L); LOG_INFO(logger, "test lazy example {} {} {} {} {} {} {}", 8ULL, std::string("str1"), std::string_view("view2"), "example2", std::string("str2"), static_cast(9), 4.0f); LOG_INFO(logger, "jumps example over dog {} {} {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, std::string("str2"), "example2", true, static_cast(9), 4.0f, 5L, "example3", false); LOG_INFO(logger, "logging example test {} {} {} {}", static_cast(10), "example1", static_cast(9), "example2"); LOG_INFO(logger, "quick fox test brown {} {} {}", 6LL, true, 7UL); LOG_INFO(logger, "over logging test lazy {} {} {} {}", 1, 8ULL, static_cast(9), "example1"); LOG_INFO(logger, "example lazy quick {} {} {} {} {} {} {} {}", "example2", "example1", 7UL, 1, std::string("str2"), std::string("str1"), 6LL, 4.0f); LOG_INFO(logger, "lazy brown dog {}", static_cast(9)); LOG_INFO(logger, "test quick jumps example {}", 6LL); LOG_INFO(logger, "dog quick lazy {} {} {} {} {} {} {}", static_cast(10), std::string("str1"), 5L, 8ULL, "example3", 3.0, "example2"); LOG_INFO(logger, "brown logging lazy quick {} {} {} {} {} {}", 2, 7UL, "example2", true, "example3", static_cast(9)); LOG_INFO(logger, "test brown fox dog {} {} {} {} {}", std::string("str1"), "example3", false, std::string_view("view1"), 6LL); LOG_INFO(logger, "logging test over dog {}", std::string_view("view1")); LOG_INFO(logger, "test dog brown {} {} {} {}", 3.0, 1, 6LL, std::string_view("view1")); LOG_INFO(logger, "example test quick {}", std::string_view("view2")); LOG_INFO(logger, "dog over fox {} {} {} {} {}", 6LL, static_cast(9), 4.0f, 2, true); LOG_INFO(logger, "logging test fox {} {} {}", 1, 3.0, 7UL); LOG_INFO(logger, "over lazy dog jumps {} {} {} {} {}", std::string("str1"), false, std::string_view("view2"), 6LL, static_cast(10)); LOG_INFO(logger, "test quick over example {} {} {} {} {} {} {} {}", std::string_view("view1"), 3.0, 6LL, 5L, static_cast(9), 2, 7UL, false); LOG_INFO(logger, "example test lazy logging {}", 3.0); LOG_INFO(logger, "jumps lazy quick over {} {} {} {} {} {} {}", std::string_view("view2"), false, std::string("str1"), true, 6LL, 1, 2); LOG_INFO(logger, "fox jumps quick {} {} {} {} {}", true, static_cast(10), "example3", 1, "example2"); LOG_INFO(logger, "jumps dog lazy {} {} {} {} {} {} {} {}", false, std::string_view("view2"), 4.0f, "example2", static_cast(9), std::string("str2"), 3.0, std::string_view("view1")); LOG_INFO(logger, "fox lazy logging jumps {}", 1); LOG_INFO(logger, "brown fox example {} {}", "example3", static_cast(9)); LOG_INFO(logger, "fox lazy jumps logging {} {} {} {} {} {}", std::string_view("view2"), 4.0f, 2, 6LL, 5L, 3.0); LOG_INFO(logger, "fox lazy logging jumps {} {} {} {} {} {} {}", std::string("str2"), std::string_view("view1"), 6LL, 1, std::string_view("view2"), 5L, static_cast(9)); LOG_INFO(logger, "quick dog jumps {} {}", std::string("str1"), 6LL); LOG_INFO(logger, "dog quick jumps example {} {} {} {} {} {} {} {}", 1, 3.0, false, 6LL, static_cast(9), "example2", 4.0f, static_cast(10)); LOG_INFO(logger, "quick example logging brown {} {} {} {} {} {} {}", 5L, "example3", 4.0f, 7UL, static_cast(10), "example2", false); LOG_INFO(logger, "lazy jumps test {} {} {} {} {} {} {} {}", 2, true, 4.0f, 8ULL, std::string_view("view1"), 6LL, "example2", std::string_view("view2")); LOG_INFO(logger, "lazy jumps dog {} {} {} {} {} {} {}", std::string_view("view1"), "example3", "example2", static_cast(9), "example1", 6LL, std::string_view("view2")); LOG_INFO(logger, "jumps quick test {} {} {} {} {} {} {} {}", 2, 8ULL, std::string("str1"), false, 1, std::string_view("view1"), static_cast(9), std::string("str2")); LOG_INFO(logger, "example jumps lazy {} {} {} {} {}", 7UL, "example2", 3.0, std::string("str2"), true); LOG_INFO(logger, "jumps quick over example {} {} {}", 6LL, 7UL, std::string("str2")); LOG_INFO(logger, "lazy dog jumps test {} {}", 7UL, true); LOG_INFO(logger, "lazy jumps example {} {} {} {} {} {} {} {} {}", false, 7UL, true, 5L, "example3", std::string("str2"), "example2", 1, static_cast(9)); LOG_INFO(logger, "dog logging fox lazy {} {} {} {} {}", 8ULL, static_cast(10), std::string("str1"), 7UL, 6LL); LOG_INFO(logger, "logging over fox lazy {} {} {} {} {} {} {} {}", 2, std::string_view("view2"), true, 6LL, std::string("str2"), 8ULL, std::string("str1"), 1); LOG_INFO(logger, "lazy fox brown {} {}", "example1", "example3"); LOG_INFO(logger, "fox quick test over {} {} {}", "example3", 1, std::string("str2")); LOG_INFO(logger, "lazy over brown {} {} {} {} {} {} {} {}", true, std::string_view("view1"), 7UL, 5L, std::string("str1"), std::string("str2"), 4.0f, static_cast(9)); LOG_INFO(logger, "test jumps brown dog {} {} {} {} {} {} {} {} {} {}", 8ULL, "example1", "example3", 1, static_cast(9), std::string_view("view2"), 4.0f, std::string_view("view1"), 3.0, 7UL); LOG_INFO(logger, "fox example jumps {}", static_cast(10)); LOG_INFO(logger, "dog lazy quick {} {} {} {} {} {}", false, static_cast(9), std::string_view("view1"), 1, "example3", std::string("str1")); LOG_INFO(logger, "jumps fox over logging {} {}", 1, "example1"); LOG_INFO(logger, "lazy example test {} {} {}", 4.0f, 7UL, 8ULL); LOG_INFO(logger, "fox brown example {} {} {} {} {}", std::string_view("view1"), std::string("str1"), std::string("str2"), std::string_view("view2"), 4.0f); LOG_INFO(logger, "logging lazy jumps {} {} {} {} {} {} {}", 4.0f, 5L, static_cast(9), 6LL, false, std::string_view("view2"), static_cast(10)); LOG_INFO(logger, "fox over logging {} {} {} {} {} {} {} {} {} {}", std::string_view("view2"), 5L, 8ULL, "example3", 6LL, false, 2, "example1", 7UL, static_cast(9)); LOG_INFO(logger, "over example logging dog {} {} {} {} {} {}", 4.0f, 8ULL, "example2", true, static_cast(10), static_cast(9)); LOG_INFO(logger, "example lazy dog {} {} {} {} {}", 8ULL, std::string_view("view2"), std::string("str2"), std::string("str1"), 1); LOG_INFO(logger, "fox example quick dog {} {} {} {} {} {} {} {} {}", "example2", false, 5L, 7UL, std::string("str2"), static_cast(9), true, "example1", "example3"); LOG_INFO(logger, "logging quick over {} {} {} {} {} {} {} {} {} {}", 2, 4.0f, "example3", std::string("str2"), std::string("str1"), 7UL, static_cast(10), "example2", 8ULL, 3.0); LOG_INFO(logger, "fox over jumps brown {} {} {} {} {} {} {} {}", std::string_view("view2"), std::string("str2"), "example2", 3.0, 5L, false, "example3", 6LL); LOG_INFO(logger, "test logging quick dog {} {} {} {} {} {} {} {} {}", 6LL, 3.0, "example2", true, false, static_cast(10), std::string("str2"), std::string("str1"), 8ULL); LOG_INFO(logger, "test logging quick lazy {} {}", std::string_view("view2"), 4.0f); LOG_INFO(logger, "logging brown example {} {} {}", 4.0f, "example1", std::string("str2")); LOG_INFO(logger, "jumps test over {} {}", std::string("str1"), std::string("str2")); LOG_INFO(logger, "fox jumps quick {} {} {} {} {} {}", 6LL, std::string("str2"), false, 7UL, std::string_view("view2"), 4.0f); LOG_INFO(logger, "quick over jumps logging {}", false); LOG_INFO(logger, "test dog logging {} {} {} {} {}", std::string("str2"), 5L, "example2", static_cast(10), 1); LOG_INFO(logger, "example dog jumps lazy {} {} {} {} {}", "example2", 2, 7UL, false, static_cast(9)); LOG_INFO(logger, "example test logging {} {} {} {} {} {} {} {} {} {}", 6LL, 1, 3.0, static_cast(10), std::string("str1"), "example2", 5L, "example3", 4.0f, static_cast(9)); LOG_INFO(logger, "lazy brown over logging {}", 7UL); LOG_INFO(logger, "over lazy quick fox {} {} {} {} {}", 8ULL, 1, 7UL, 5L, "example3"); LOG_INFO(logger, "over example fox {} {} {}", true, 2, static_cast(9)); LOG_INFO(logger, "fox over brown jumps {} {} {}", std::string_view("view2"), 5L, 4.0f); LOG_INFO(logger, "brown jumps quick {}", "example1"); LOG_INFO(logger, "test jumps lazy {} {} {} {} {}", 6LL, 8ULL, 4.0f, "example1", 2); LOG_INFO(logger, "dog fox lazy {} {}", 3.0, false); LOG_INFO(logger, "jumps test quick brown {} {} {} {} {} {} {} {}", "example3", 7UL, 2, std::string_view("view1"), false, true, "example1", "example2"); LOG_INFO(logger, "dog over quick {} {} {} {} {} {} {} {} {} {}", 2, 5L, "example2", 7UL, "example3", std::string_view("view1"), std::string_view("view2"), std::string("str1"), false, "example1"); LOG_INFO(logger, "quick dog over brown {} {} {} {} {}", 6LL, 4.0f, "example1", 3.0, 1); LOG_INFO(logger, "logging over fox {} {}", 2, "example3"); LOG_INFO(logger, "quick logging example {} {} {} {}", 7UL, 4.0f, 1, 8ULL); LOG_INFO(logger, "quick fox brown {} {} {} {} {}", 5L, 3.0, 2, false, "example3"); LOG_INFO(logger, "quick lazy logging test {} {} {}", static_cast(10), 7UL, 2); LOG_INFO(logger, "example lazy logging {} {} {} {} {}", static_cast(10), 1, 8ULL, 7UL, static_cast(9)); LOG_INFO(logger, "lazy quick logging brown {} {} {} {} {} {} {} {}", static_cast(9), 3.0, 7UL, true, 5L, std::string_view("view2"), std::string("str1"), "example2"); LOG_INFO(logger, "over fox test {} {} {}", false, std::string_view("view2"), 8ULL); LOG_INFO(logger, "test dog example jumps {} {} {} {}", "example2", 2, true, 8ULL); LOG_INFO(logger, "quick lazy dog test {} {} {} {} {} {} {} {} {} {}", 6LL, std::string_view("view2"), false, "example2", std::string_view("view1"), static_cast(9), "example3", static_cast(10), 1, std::string("str2")); LOG_INFO(logger, "over example quick {} {} {} {} {} {} {} {} {} {}", static_cast(10), "example3", "example2", 2, 4.0f, std::string_view("view2"), "example1", false, 8ULL, true); LOG_INFO(logger, "lazy test fox dog {} {} {} {} {} {}", std::string_view("view1"), 5L, 2, 4.0f, static_cast(9), 1); LOG_INFO(logger, "jumps lazy test brown {}", true); LOG_INFO(logger, "brown fox over {} {} {} {} {} {} {} {}", 4.0f, 8ULL, 3.0, 5L, 2, 6LL, std::string_view("view1"), 1); LOG_INFO(logger, "logging over quick test {} {} {} {} {} {} {}", 4.0f, static_cast(9), 1, 6LL, "example2", 5L, std::string_view("view1")); LOG_INFO(logger, "logging test dog {} {} {} {} {} {} {}", static_cast(10), "example3", 2, false, 3.0, 6LL, 4.0f); LOG_INFO(logger, "example brown dog test {} {} {} {} {}", 6LL, 8ULL, true, 3.0, std::string_view("view1")); LOG_INFO(logger, "logging test jumps quick {} {} {} {}", "example3", 3.0, std::string("str1"), 7UL); LOG_INFO(logger, "dog lazy quick {} {} {}", 2, true, static_cast(9)); LOG_INFO(logger, "quick over example fox {} {} {} {} {} {} {}", 8ULL, static_cast(9), 6LL, 3.0, 7UL, "example1", 1); LOG_INFO(logger, "jumps example fox {} {} {} {} {} {}", std::string_view("view2"), true, 8ULL, static_cast(10), "example2", false); LOG_INFO(logger, "jumps logging brown {} {} {} {}", true, std::string_view("view2"), 7UL, std::string("str1")); LOG_INFO(logger, "test fox jumps {} {} {}", 2, "example3", static_cast(9)); LOG_INFO(logger, "jumps lazy quick {}", "example2"); LOG_INFO(logger, "logging brown over {} {} {} {} {}", "example1", 5L, 3.0, 7UL, 4.0f); LOG_INFO(logger, "dog lazy quick test {} {} {} {}", "example3", std::string_view("view1"), 6LL, std::string_view("view2")); LOG_INFO(logger, "jumps lazy dog {} {} {}", static_cast(9), std::string_view("view2"), "example2"); LOG_INFO(logger, "over fox brown lazy {} {} {} {} {} {} {}", 7UL, 2, "example1", "example3", 5L, std::string("str2"), 6LL); LOG_INFO(logger, "logging over test {} {} {} {} {} {}", std::string_view("view2"), 1, false, 2, true, 8ULL); LOG_INFO(logger, "jumps dog over test {} {} {} {} {} {} {} {} {} {}", 1, "example3", false, 2, 8ULL, 3.0, 7UL, 5L, static_cast(10), std::string_view("view2")); LOG_INFO(logger, "brown test lazy {} {} {} {} {} {} {} {} {}", std::string("str2"), 4.0f, 5L, 2, "example3", static_cast(10), 8ULL, static_cast(9), std::string_view("view1")); LOG_INFO(logger, "over dog brown {} {}", "example2", 5L); LOG_INFO(logger, "fox lazy over logging {} {} {} {} {} {} {} {} {} {}", std::string("str1"), "example2", 2, 1, std::string_view("view1"), 5L, 3.0, true, 8ULL, 7UL); LOG_INFO(logger, "fox example over logging {} {} {} {} {}", 2, std::string_view("view1"), static_cast(9), 5L, std::string("str2")); LOG_INFO(logger, "lazy dog over fox {} {} {} {} {} {} {}", std::string("str1"), 3.0, false, 7UL, 1, std::string("str2"), 2); LOG_INFO(logger, "brown fox quick lazy {} {}", 8ULL, std::string_view("view1")); LOG_INFO(logger, "example logging brown lazy {} {} {} {} {} {} {} {} {}", 8ULL, 6LL, 2, true, std::string("str2"), static_cast(9), 7UL, "example2", "example3"); LOG_INFO(logger, "quick over logging brown {} {} {} {}", true, static_cast(10), 1, 4.0f); LOG_INFO(logger, "brown over fox {} {}", std::string("str2"), 8ULL); LOG_INFO(logger, "over jumps quick {} {}", false, static_cast(9)); LOG_INFO(logger, "quick test example {} {} {} {} {} {} {} {} {} {}", static_cast(9), std::string("str2"), 3.0, 2, 1, std::string_view("view1"), "example2", false, 8ULL, 5L); LOG_INFO(logger, "brown lazy dog test {} {}", static_cast(10), 3.0); LOG_INFO(logger, "jumps fox dog {}", std::string_view("view1")); LOG_INFO(logger, "dog fox brown {} {} {} {} {} {} {}", 1, 4.0f, 5L, 8ULL, 3.0, "example1", "example3"); LOG_INFO(logger, "test lazy over {} {} {} {} {} {} {} {}", false, true, std::string_view("view2"), 3.0, "example3", 7UL, 1, "example1"); LOG_INFO(logger, "fox dog brown logging {} {} {} {} {}", false, true, 7UL, "example3", std::string("str2")); LOG_INFO(logger, "over dog lazy example {} {}", false, "example3"); LOG_INFO(logger, "lazy jumps dog {} {} {} {}", 4.0f, std::string("str1"), "example2", false); LOG_INFO(logger, "lazy test fox {} {} {} {} {} {} {}", 7UL, true, std::string_view("view2"), 2, 3.0, std::string_view("view1"), 4.0f); LOG_INFO(logger, "example jumps test {} {} {} {} {} {} {} {} {} {}", static_cast(9), static_cast(10), 4.0f, std::string("str2"), true, "example3", std::string_view("view2"), false, 6LL, 3.0); LOG_INFO(logger, "logging brown fox {} {}", std::string_view("view2"), 8ULL); LOG_INFO(logger, "lazy test dog jumps {} {} {}", 2, 8ULL, 4.0f); LOG_INFO(logger, "fox dog jumps {} {} {} {} {} {} {} {} {} {}", 8ULL, std::string("str2"), false, static_cast(9), std::string_view("view2"), static_cast(10), std::string_view("view1"), "example1", 3.0, 7UL); return 0; }quill-12.1.0/benchmarks/compile_time/gen_log_messages.py000066400000000000000000000047021522564103500233650ustar00rootroot00000000000000import random from pathlib import Path OUTPUT_FILE = Path(__file__).with_name("compile_time_bench.cpp") RNG_SEED = 1337 def generate_log_statements(num_statements): rng = random.Random(RNG_SEED) argument_types = [ '1', '2', '3.0', '4.0f', '5L', '6LL', '7UL', '8ULL', 'true', 'false', '"example1"', '"example2"', '"example3"', 'std::string("str1")', 'std::string("str2")', 'std::string_view("view1")', 'std::string_view("view2")', 'static_cast(9)', 'static_cast(10)' ] random_words = ["quick", "brown", "fox", "jumps", "over", "lazy", "dog", "logging", "test", "example"] statements = [] for i in range(num_statements): num_args = rng.randint(1, 10) # Number of arguments for the log statement args = rng.sample(argument_types, num_args) placeholders = ' '.join(["{}" for _ in args]) num_words = rng.randint(3, 4) # Number of random words in the log message words = ' '.join(rng.sample(random_words, num_words)) statement = f' LOG_INFO(logger, "{words} {placeholders}", {", ".join(args)});' statements.append(statement) return statements def write_to_file(filename, statements): with open(filename, 'w') as f: f.write('#include "quill/Backend.h"\n') f.write('#include "quill/Frontend.h"\n') f.write('#include "quill/LogMacros.h"\n') f.write('#include "quill/Logger.h"\n') f.write('#include "quill/sinks/ConsoleSink.h"\n') f.write('#include \n') f.write('#include \n\n') f.write('/**\n') f.write(' * Trivial logging example to console\n') f.write(' */\n\n') f.write('int main()\n') f.write('{\n') f.write(' // Start the backend thread\n') f.write(' quill::BackendOptions backend_options;\n') f.write(' quill::Backend::start(backend_options);\n\n') f.write(' // Frontend\n') f.write(' auto console_sink = quill::Frontend::create_or_get_sink("sink_id_1");\n') f.write(' quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(console_sink));\n\n') for statement in statements: f.write(f'{statement}\n') f.write('\n return 0;\n') f.write('}\n') if __name__ == '__main__': num_statements = 2000 statements = generate_log_statements(num_statements) write_to_file(OUTPUT_FILE, statements) quill-12.1.0/benchmarks/compile_time/qwrapper/000077500000000000000000000000001522564103500213505ustar00rootroot00000000000000quill-12.1.0/benchmarks/compile_time/qwrapper/CMakeLists.txt000066400000000000000000000007371522564103500241170ustar00rootroot00000000000000set(LIB_NAME qwrapper_compile_time_bench) add_library(${LIB_NAME} STATIC include/qwrapper/qwrapper.h include/qwrapper/qwrapper.cpp) # Add include directories for this library target_include_directories(${LIB_NAME} PUBLIC $ $ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) # Link quill dependency target_link_libraries(${LIB_NAME} PUBLIC quill::quill)quill-12.1.0/benchmarks/compile_time/qwrapper/include/000077500000000000000000000000001522564103500227735ustar00rootroot00000000000000quill-12.1.0/benchmarks/compile_time/qwrapper/include/qwrapper/000077500000000000000000000000001522564103500246345ustar00rootroot00000000000000quill-12.1.0/benchmarks/compile_time/qwrapper/include/qwrapper/qwrapper.cpp000066400000000000000000000011651522564103500272040ustar00rootroot00000000000000#include "qwrapper.h" #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/Logger.h" #include "quill/sinks/ConsoleSink.h" void setup_quill(char const* log_file) { quill::Backend::start(); auto console_sink = quill::Frontend::create_or_get_sink("s1"); quill::Frontend::create_or_get_logger( "root", std::move(console_sink), quill::PatternFormatterOptions{"%(time) [%(thread_id)] %(short_source_location:<28) " "LOG_%(log_level:<9) %(logger:<12) %(message)", "%H:%M:%S.%Qns", quill::Timezone::GmtTime}); }quill-12.1.0/benchmarks/compile_time/qwrapper/include/qwrapper/qwrapper.h000066400000000000000000000000651522564103500266470ustar00rootroot00000000000000#pragma once void setup_quill(char const* log_file);quill-12.1.0/benchmarks/hot_path_latency/000077500000000000000000000000001522564103500203665ustar00rootroot00000000000000quill-12.1.0/benchmarks/hot_path_latency/CMakeLists.txt000066400000000000000000000013251522564103500231270ustar00rootroot00000000000000add_executable(BENCHMARK_quill_hot_path_rdtsc_clock hot_path_bench_config.h hot_path_bench.h quill_hot_path_rdtsc_clock.cpp) set_common_compile_options(BENCHMARK_quill_hot_path_rdtsc_clock) target_compile_definitions(BENCHMARK_quill_hot_path_rdtsc_clock PRIVATE QUILL_ENABLE_IMMEDIATE_FLUSH=0) target_link_libraries(BENCHMARK_quill_hot_path_rdtsc_clock quill) add_executable(BENCHMARK_quill_hot_path_system_clock hot_path_bench_config.h hot_path_bench.h quill_hot_path_system_clock.cpp) set_common_compile_options(BENCHMARK_quill_hot_path_system_clock) target_compile_definitions(BENCHMARK_quill_hot_path_system_clock PRIVATE QUILL_ENABLE_IMMEDIATE_FLUSH=0) target_link_libraries(BENCHMARK_quill_hot_path_system_clock quill)quill-12.1.0/benchmarks/hot_path_latency/hot_path_bench.h000066400000000000000000000222031522564103500235030ustar00rootroot00000000000000/** * Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors. * Distributed under the MIT License (http://opensource.org/licenses/MIT) */ #pragma once #include "hot_path_bench_config.h" #include "quill/backend/BackendUtilities.h" #include "quill/backend/RdtscClock.h" #include "quill/core/Rdtsc.h" #include #include #include #include #include #include #include #include #include #include #include // Pinning can legitimately fail (e.g. Apple Silicon does not support the affinity policy); // warn and continue instead of terminating the benchmark inline void try_set_cpu_affinity(std::vector const& cpus) { #if defined(QUILL_NO_EXCEPTIONS) quill::detail::set_cpu_affinity(cpus); #else try { quill::detail::set_cpu_affinity(cpus); } catch (std::exception const& e) { std::cerr << "Failed to set cpu affinity: " << e.what() << std::endl; } #endif } inline uint16_t get_cpu_to_pin_thread(uint16_t thread_num) { auto const num_cores = static_cast(std::thread::hardware_concurrency()); // If hardware_concurrency feature is not supported, zero value is returned. if (num_cores == 0) return 0; return thread_num % num_cores; } // Instead of sleep inline void wait([[maybe_unused]] std::chrono::nanoseconds min, std::chrono::nanoseconds max) { #ifdef PERF_ENABLED // when in perf use sleep as the other variables add noise std::this_thread::sleep_for(max); #else thread_local std::mt19937 gen{std::random_device{}()}; std::uniform_int_distribution dis(min.count(), max.count()); auto const start_time = std::chrono::steady_clock::now(); auto const end_time = start_time + std::chrono::nanoseconds{dis(gen)}; std::chrono::nanoseconds time_now; do { time_now = std::chrono::steady_clock::now().time_since_epoch(); } while (time_now < end_time.time_since_epoch()); #endif } inline size_t messages_for_thread(size_t messages_per_iteration, uint16_t thread_count, uint16_t thread_num) noexcept { if (thread_count == 0) { return 0; } size_t const base_messages_per_thread = messages_per_iteration / thread_count; size_t const remainder = messages_per_iteration % thread_count; return base_messages_per_thread + (static_cast(thread_num) < remainder ? 1u : 0u); } inline void wait_for_all_threads_to_start(std::atomic& started_threads, size_t participant_count) noexcept { started_threads.fetch_add(1, std::memory_order_acq_rel); while (started_threads.load(std::memory_order_acquire) != participant_count) { } } #ifdef PERF_ENABLED /***/ inline void run_log_benchmark(size_t num_iterations, size_t messages_per_iteration, std::function on_thread_start, std::function log_func, std::function on_thread_exit, std::atomic& started_threads, size_t participant_count, size_t current_thread_num) { // running thread affinity try_set_cpu_affinity({get_cpu_to_pin_thread(static_cast(current_thread_num))}); on_thread_start(); wait_for_all_threads_to_start(started_threads, participant_count); if (messages_per_iteration == 0) { on_thread_exit(); return; } // Main Benchmark for (size_t iteration = 0; iteration < num_iterations; ++iteration) { double const d = iteration + (0.1 * iteration); for (size_t i = 0; i < messages_per_iteration; ++i) { log_func(iteration, i, d); } // send the next batch of messages after x time wait(MIN_WAIT_DURATION, MAX_WAIT_DURATION); } on_thread_exit(); } #else /***/ inline void run_log_benchmark(size_t num_iterations, size_t messages_per_iteration, std::function const& on_thread_start, std::function const& log_func, std::function const& on_thread_exit, std::atomic& started_threads, size_t participant_count, uint16_t current_thread_num, std::vector& latencies, double rdtsc_ns_per_tick) { // running thread affinity try_set_cpu_affinity({get_cpu_to_pin_thread(current_thread_num)}); on_thread_start(); wait_for_all_threads_to_start(started_threads, participant_count); if (messages_per_iteration == 0) { on_thread_exit(); return; } // Main Benchmark for (size_t iteration = 0; iteration < num_iterations; ++iteration) { double const d = static_cast(iteration) + (0.1 * static_cast(iteration)); auto const start = quill::detail::rdtsc(); for (size_t i = 0; i < messages_per_iteration; ++i) { log_func(iteration, i, d); } auto const end = quill::detail::rdtsc(); uint64_t const latency{static_cast( static_cast((end - start)) / static_cast(messages_per_iteration) * rdtsc_ns_per_tick)}; latencies.push_back(latency); // send the next batch of messages after x time wait(MIN_WAIT_DURATION, MAX_WAIT_DURATION); } on_thread_exit(); } #endif /***/ inline void run_benchmark([[maybe_unused]] char const* benchmark_name, uint16_t thread_count, size_t num_iterations, [[maybe_unused]] size_t messages_per_iteration, std::function const& on_thread_start, std::function const& log_func, std::function const& on_thread_exit) { if (thread_count == 0) { #ifndef PERF_ENABLED std::cout << "Thread Count 0 - Total messages 0 - " << benchmark_name << "\n | no latency samples |\n\n"; #endif return; } // main thread affinity try_set_cpu_affinity({0}); #ifndef PERF_ENABLED std::cout << "running for " << thread_count << " thread(s)" << std::endl; quill::detail::RdtscClock rdtsc_clock{std::chrono::minutes{30}}; // each thread gets a vector of latencies std::vector> latencies; latencies.resize(thread_count); for (auto& elem : latencies) { elem.reserve(num_iterations); } #endif std::vector threads; threads.reserve(thread_count); std::atomic started_threads{0}; for (uint16_t thread_num = 0; thread_num < thread_count; ++thread_num) { size_t const thread_messages_per_iteration = messages_for_thread(messages_per_iteration, thread_count, thread_num); #ifdef PERF_ENABLED // Spawn num threads threads.emplace_back(run_log_benchmark, num_iterations, thread_messages_per_iteration, on_thread_start, log_func, on_thread_exit, std::ref(started_threads), static_cast(thread_count), thread_num + 1); #else // Spawn num threads threads.emplace_back(run_log_benchmark, num_iterations, thread_messages_per_iteration, std::ref(on_thread_start), std::ref(log_func), std::ref(on_thread_exit), std::ref(started_threads), static_cast(thread_count), static_cast(thread_num + 1u), std::ref(latencies[thread_num]), rdtsc_clock.nanoseconds_per_tick()); #endif } // Wait for threads to finish for (uint16_t i = 0; i < thread_count; ++i) { threads[i].join(); } #ifndef PERF_ENABLED // All threads have finished we can read all latencies std::vector latencies_combined; latencies_combined.reserve(num_iterations * thread_count); for (auto const& elem : latencies) { latencies_combined.insert(latencies_combined.end(), elem.begin(), elem.end()); } // Sort all latencies std::sort(latencies_combined.begin(), latencies_combined.end()); size_t const total_messages = num_iterations * messages_per_iteration; if (latencies_combined.empty()) { std::cout << "Thread Count " << thread_count << " - Total messages " << total_messages << " - " << benchmark_name << "\n | no latency samples |\n\n"; return; } size_t const sample_count = latencies_combined.size(); auto percentile_index = [sample_count](double percentile) { size_t const nearest_rank = static_cast(std::ceil(static_cast(sample_count) * percentile)); return std::min(sample_count - 1, nearest_rank == 0 ? size_t{0} : (nearest_rank - 1)); }; std::cout << "Thread Count " << thread_count << " - Total messages " << total_messages << " - " << benchmark_name << "\n | 50th | 75th | 90th | 95th | 99th | 99.9th | Worst |\n" << " | " << latencies_combined[percentile_index(0.5)] << " | " << latencies_combined[percentile_index(0.75)] << " | " << latencies_combined[percentile_index(0.9)] << " | " << latencies_combined[percentile_index(0.95)] << " | " << latencies_combined[percentile_index(0.99)] << " | " << latencies_combined[percentile_index(0.999)] << " | " << latencies_combined[static_cast(latencies_combined.size() - 1)] << " |\n\n"; #endif } quill-12.1.0/benchmarks/hot_path_latency/hot_path_bench_config.h000066400000000000000000000023311522564103500250300ustar00rootroot00000000000000/** * Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors. * Distributed under the MIT License (http://opensource.org/licenses/MIT) */ #pragma once #include /** * When running the benchmark using e.g. perf, enable this definition to remove extra noise * from calculating and printing the results. * * To see shared cached lines : * perf c2c record -g --call-graph dwarf,8192 ./benchmark_quill_call_site_latency * perf c2c report -NN -g --call-graph -c pid,iaddr --stdio * perf c2c report -NN -g --call-graph -d lcl --stdio */ // #define PERF_ENABLED #define THREAD_LIST_COUNT std::vector{1, 4} #define MESSAGES_PER_ITERATION std::size_t{20} #define ITERATIONS std::size_t{10000} /** * Min-Max wait duration between each iteration - This lets the backend thread catch up * a little bit with the caller thread, because the caller thread is so much faster. * When the backend thread can't catch up it will cause the caller thread on the hot path * to reallocate more space in the queue slowing it down. * This benchmark is measuring latency not high throughput * **/ #define MIN_WAIT_DURATION std::chrono::microseconds{2000} #define MAX_WAIT_DURATION std::chrono::microseconds{2200} quill-12.1.0/benchmarks/hot_path_latency/quill_hot_path_rdtsc_clock.cpp000066400000000000000000000055151522564103500264660ustar00rootroot00000000000000/** * Adding a benchmark for a another logger should be straight forward by duplicating and modifying * this file. */ #include "hot_path_bench.h" #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/sinks/FileSink.h" struct FrontendOptions : quill::FrontendOptions { }; using Frontend = quill::FrontendImpl; using Logger = quill::LoggerImpl; /***/ void quill_benchmark(std::vector const& thread_count_array, size_t num_iterations_per_thread, size_t messages_per_iteration) { /** - MAIN THREAD START - Logger setup if any **/ /** - Setup Quill **/ quill::BackendOptions backend_options; backend_options.cpu_affinity = {5}; backend_options.sleep_duration = std::chrono::nanoseconds{0}; // Start the logging backend thread and give it some tiem to init quill::Backend::start(backend_options); // wait for the backend thread to start std::this_thread::sleep_for(std::chrono::seconds(1)); // Create a file sink to write to a file std::shared_ptr file_sink = Frontend::create_or_get_sink( "quill_hot_path_rdtsc_clock.log", []() { quill::FileSinkConfig cfg; cfg.set_open_mode('w'); return cfg; }(), quill::FileEventNotifier{}); Logger* logger = Frontend::create_or_get_logger( "bench_logger", std::move(file_sink), quill::PatternFormatterOptions{ "%(time) [%(thread_id)] %(short_source_location) %(log_level) %(message)", "%H:%M:%S.%Qns", quill::Timezone::LocalTime, false}); /** LOGGING THREAD FUNCTIONS - on_start, on_exit, log_func must be implemented **/ /** those run on a several thread(s). It can be one or multiple threads based on THREAD_LIST_COUNT config */ auto on_start = [logger]() { // on thread start LOG_INFO(logger, "preallocate"); logger->flush_log(0); }; auto on_exit = [logger]() { // on thread exit we block flush, so the next benchmark starts with the backend thread ready // to process the messages logger->flush_log(); }; // on main auto log_func = [logger](uint64_t k, uint64_t i, double d) { // Main logging function. // Across all logging threads, each iteration emits messages_per_iteration log calls in total. // hot_path_bench.h distributes that work across threads. LOG_INFO(logger, "Logging iteration: {}, message: {}, double: {}", k, i, d); }; /** ALWAYS REQUIRED **/ // Run the benchmark for n threads for (auto thread_count : thread_count_array) { run_benchmark("Logger: Quill - Benchmark: Hot Path Latency / Nanoseconds", thread_count, num_iterations_per_thread, messages_per_iteration, on_start, log_func, on_exit); } } /***/ int main(int, char**) { quill_benchmark(THREAD_LIST_COUNT, ITERATIONS, MESSAGES_PER_ITERATION); } quill-12.1.0/benchmarks/hot_path_latency/quill_hot_path_system_clock.cpp000066400000000000000000000056621522564103500266760ustar00rootroot00000000000000/** * Adding a benchmark for a another logger should be straight forward by duplicating and modifying * this file. */ #include "hot_path_bench.h" #include "quill/Backend.h" #include "quill/Frontend.h" #include "quill/LogMacros.h" #include "quill/sinks/FileSink.h" struct FrontendOptions : quill::FrontendOptions { }; using Frontend = quill::FrontendImpl; using Logger = quill::LoggerImpl; /***/ void quill_benchmark(std::vector const& thread_count_array, size_t num_iterations_per_thread, size_t messages_per_iteration) { /** - MAIN THREAD START - Logger setup if any **/ /** - Setup Quill **/ quill::BackendOptions backend_options; backend_options.cpu_affinity = {5}; backend_options.sleep_duration = std::chrono::nanoseconds{0}; // Start the logging backend thread and give it some tiem to init quill::Backend::start(backend_options); std::this_thread::sleep_for(std::chrono::milliseconds{100}); // wait for the backend thread to start std::this_thread::sleep_for(std::chrono::seconds(1)); // Create a file sink to write to a file std::shared_ptr file_sink = Frontend::create_or_get_sink( "quill_hot_path_system_clock.log", []() { quill::FileSinkConfig cfg; cfg.set_open_mode('w'); return cfg; }(), quill::FileEventNotifier{}); Logger* logger = Frontend::create_or_get_logger( "bench_logger", std::move(file_sink), quill::PatternFormatterOptions{ "%(time) [%(thread_id)] %(short_source_location) %(log_level) %(message)", "%H:%M:%S.%Qns", quill::Timezone::LocalTime, false}, quill::ClockSourceType::System); /** LOGGING THREAD FUNCTIONS - on_start, on_exit, log_func must be implemented **/ /** those run on a several thread(s). It can be one or multiple threads based on THREAD_LIST_COUNT config */ auto on_start = [logger]() { // on thread start LOG_INFO(logger, "preallocate"); logger->flush_log(0); }; auto on_exit = [logger]() { // on thread exit we block flush, so the next benchmark starts with the backend thread ready // to process the messages logger->flush_log(); }; // on main auto log_func = [logger](uint64_t k, uint64_t i, double d) { // Main logging function. // Across all logging threads, each iteration emits messages_per_iteration log calls in total. // hot_path_bench.h distributes that work across threads. LOG_INFO(logger, "Logging iteration: {}, message: {}, double: {}", k, i, d); }; /** ALWAYS REQUIRED **/ // Run the benchmark for n threads for (auto thread_count : thread_count_array) { run_benchmark("Logger: Quill - Benchmark: Hot Path Latency / Nanoseconds", thread_count, num_iterations_per_thread, messages_per_iteration, on_start, log_func, on_exit); } } /***/ int main(int, char**) { quill_benchmark(THREAD_LIST_COUNT, ITERATIONS, MESSAGES_PER_ITERATION); } quill-12.1.0/cmake/000077500000000000000000000000001522564103500140045ustar00rootroot00000000000000quill-12.1.0/cmake/CodeCoverage.cmake000066400000000000000000000133611522564103500173400ustar00rootroot00000000000000# 2012-01-31, Lars Bilke # - Enable Code Coverage # # 2013-09-17, Joakim Söderberg # - Added support for Clang. # - Some additional usage instructions. # # 2018-03-31, Bendik Samseth # - Relax debug output. # - Keep a copy of the coverage output for later use. # - Updated coverage exclude patterns. # # 2018-01-03, HenryRLee # - Allow for *Clang compiler names, not just Clang. # # 2018-01-03, Bendik Samseth # - Only check compiler compatibility if in a coverage build. # # # USAGE: # 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here: # http://stackoverflow.com/a/22404544/80480 # # 1. Copy this file into your cmake modules path. # # 2. Add the following line to your CMakeLists.txt: # INCLUDE(CodeCoverage) # # 3. Set compiler flags to turn off optimization and enable coverage: # SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") # SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") # # 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target # which runs your test executable and produces a lcov code coverage report: # Example: # SETUP_TARGET_FOR_COVERAGE( # my_coverage_target # Name for custom target. # test_driver # Name of the test driver executable that runs the tests. # # NOTE! This should always have a ZERO as exit code # # otherwise the coverage generation will not complete. # coverage # Name of output directory. # ) # # 4. Build a Debug build: # cmake -DCMAKE_BUILD_TYPE=Debug .. # make # make my_coverage_target # # # Param _targetname The name of new the custom make target # Param _testrunner The name of the target which runs the tests. # MUST return ZERO always, even on errors. # If not, no coverage report will be created! # Param _outputname lcov output is generated as _outputname.info # HTML report is generated in _outputname/index.html # Optional fourth parameter is passed as arguments to _testrunner # Pass them in list form, e.g.: "-j;2" for -j 2 FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname) IF (NOT LCOV_PATH) MESSAGE(FATAL_ERROR "lcov not found! Aborting...") ENDIF () # NOT LCOV_PATH IF (NOT GENHTML_PATH) MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") ENDIF () # NOT GENHTML_PATH # Setup target ADD_CUSTOM_TARGET(${_targetname} # Cleanup lcov ${LCOV_PATH} --directory . --zerocounters # Run tests COMMAND ${_testrunner} ${ARGV3} # Capturing lcov counters and generating report COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info COMMAND ${LCOV_PATH} --remove ${_outputname}.info '*/tests/*' '/usr/*' '*/external/*' '/Applications/*' --output-file ${_outputname}.info.cleaned COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned COMMAND ${LCOV_PATH} --list ${_outputname}.info.cleaned WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." ) # Show info where to find the report ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD COMMAND ; COMMENT "${BoldMagenta}Open ./${_outputname}/index.html in your browser to view the coverage report.${ColourReset}" ) ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_tolower) if (cmake_build_type_tolower STREQUAL "coverage") # Check prereqs FIND_PROGRAM(GCOV_PATH gcov) FIND_PROGRAM(LCOV_PATH lcov) FIND_PROGRAM(GENHTML_PATH genhtml) FIND_PROGRAM(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests) IF (NOT GCOV_PATH) MESSAGE(FATAL_ERROR "gcov not found! Aborting...") ENDIF () # NOT GCOV_PATH IF (NOT CMAKE_COMPILER_IS_GNUCXX) IF (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") MESSAGE(FATAL_ERROR "Compiler is not GNU gcc or Clang! Aborting...") ENDIF () ENDIF () # NOT CMAKE_COMPILER_IS_GNUCXX SET(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE) SET(CMAKE_C_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the C compiler during coverage builds." FORCE) SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE "" CACHE STRING "Flags used for linking binaries during coverage builds." FORCE) SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "" CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE) MARK_AS_ADVANCED( CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE CMAKE_SHARED_LINKER_FLAGS_COVERAGE) # If unwanted files are included in the coverage reports, you can # adjust the exclude patterns on line 83. SETUP_TARGET_FOR_COVERAGE( coverage # Name for custom target. ${TEST_NAME} # Name of the test driver executable that runs the tests. # NOTE! This should always have a ZERO as exit code # otherwise the coverage generation will not complete. coverage_out # Name of output directory. ) else () add_custom_target(coverage COMMAND echo "${Red}Code coverage only available in coverage builds." COMMAND echo "${Green}Make a new build directory and rerun cmake with -DCMAKE_BUILD_TYPE=Coverage to enable this target.${ColorReset}" ) endif () quill-12.1.0/cmake/Doctest.cmake000066400000000000000000000176241522564103500164250ustar00rootroot00000000000000# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #[=======================================================================[.rst: doctest ----- This module defines a function to help use the doctest test framework. The :command:`doctest_discover_tests` discovers tests by asking the compiled test executable to enumerate its tests. This does not require CMake to be re-run when tests change. However, it may not work in a cross-compiling environment, and setting test properties is less convenient. This command is intended to replace use of :command:`add_test` to register tests, and will create a separate CTest test for each doctest test case. Note that this is in some cases less efficient, as common set-up and tear-down logic cannot be shared by multiple test cases executing in the same instance. However, it provides more fine-grained pass/fail information to CTest, which is usually considered as more beneficial. By default, the CTest test name is the same as the doctest name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. .. command:: doctest_discover_tests Automatically add tests with CTest by querying the compiled test executable for available tests:: doctest_discover_tests(target [TEST_SPEC arg1...] [EXTRA_ARGS arg1...] [WORKING_DIRECTORY dir] [TEST_PREFIX prefix] [TEST_SUFFIX suffix] [PROPERTIES name1 value1...] [ADD_LABELS value] [TEST_LIST var] [JUNIT_OUTPUT_DIR dir] ) ``doctest_discover_tests`` sets up a post-build command on the test executable that generates the list of tests by parsing the output from running the test with the ``--list-test-cases`` argument. This ensures that the full list of tests is obtained. Since test discovery occurs at build time, it is not necessary to re-run CMake when the list of tests changes. However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set in order to function in a cross-compiling environment. Additionally, setting properties on tests is somewhat less convenient, since the tests are not available at CMake time. Additional test properties may be assigned to the set of tests as a whole using the ``PROPERTIES`` option. If more fine-grained test control is needed, custom content may be provided through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES` directory property. The set of discovered tests is made accessible to such a script via the ``_TESTS`` variable. The options are: ``target`` Specifies the doctest executable, which must be a known CMake executable target. CMake will substitute the location of the built executable when running the test. ``TEST_SPEC arg1...`` Specifies test cases, wildcarded test cases, tags and tag expressions to pass to the doctest executable with the ``--list-test-cases`` argument. ``EXTRA_ARGS arg1...`` Any extra arguments to pass on the command line to each test case. ``WORKING_DIRECTORY dir`` Specifies the directory in which to run the discovered test cases. If this option is not provided, the current binary directory is used. ``TEST_PREFIX prefix`` Specifies a ``prefix`` to be prepended to the name of each discovered test case. This can be useful when the same test executable is being used in multiple calls to ``doctest_discover_tests()`` but with different ``TEST_SPEC`` or ``EXTRA_ARGS``. ``TEST_SUFFIX suffix`` Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may be specified. ``PROPERTIES name1 value1...`` Specifies additional properties to be set on all tests discovered by this invocation of ``doctest_discover_tests``. ``ADD_LABELS value`` Specifies if the test labels should be set automatically. ``TEST_LIST var`` Make the list of tests available in the variable ``var``, rather than the default ``_TESTS``. This can be useful when the same test executable is being used in multiple calls to ``doctest_discover_tests()``. Note that this variable is only available in CTest. ``JUNIT_OUTPUT_DIR dir`` If specified, the parameter is passed along with ``--reporters=junit`` and ``--out=`` to the test executable. The actual file name is the same as the test target, including prefix and suffix. This should be used instead of EXTRA_ARGS to avoid race conditions writing the XML result output when using parallel test execution. #]=======================================================================] #------------------------------------------------------------------------------ function(doctest_discover_tests TARGET) cmake_parse_arguments( "" "" "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;JUNIT_OUTPUT_DIR" "TEST_SPEC;EXTRA_ARGS;PROPERTIES;ADD_LABELS" ${ARGN} ) if(NOT _WORKING_DIRECTORY) set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") endif() if(NOT _TEST_LIST) set(_TEST_LIST ${TARGET}_TESTS) endif() ## Generate a unique name based on the extra arguments string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}") string(SUBSTRING ${args_hash} 0 7 args_hash) # Define rule to generate test list for aforementioned test executable set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake") set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake") get_property(crosscompiling_emulator TARGET ${TARGET} PROPERTY CROSSCOMPILING_EMULATOR ) add_custom_command( TARGET ${TARGET} POST_BUILD BYPRODUCTS "${ctest_tests_file}" COMMAND "${CMAKE_COMMAND}" -D "TEST_TARGET=${TARGET}" -D "TEST_EXECUTABLE=$" -D "TEST_EXECUTOR=${crosscompiling_emulator}" -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" -D "TEST_SPEC=${_TEST_SPEC}" -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" -D "TEST_PROPERTIES=${_PROPERTIES}" -D "TEST_ADD_LABELS=${_ADD_LABELS}" -D "TEST_PREFIX=${_TEST_PREFIX}" -D "TEST_SUFFIX=${_TEST_SUFFIX}" -D "TEST_LIST=${_TEST_LIST}" -D "TEST_JUNIT_OUTPUT_DIR=${_JUNIT_OUTPUT_DIR}" -D "CTEST_FILE=${ctest_tests_file}" -P "${_DOCTEST_DISCOVER_TESTS_SCRIPT}" VERBATIM ) file(WRITE "${ctest_include_file}" "if(EXISTS \"${ctest_tests_file}\")\n" " include(\"${ctest_tests_file}\")\n" "else()\n" " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n" "endif()\n" ) if(NOT CMAKE_VERSION VERSION_LESS 3.10) # Add discovered tests to directory TEST_INCLUDE_FILES set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" ) else() # Add discovered tests as directory TEST_INCLUDE_FILE if possible get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET) if(NOT ${test_include_file_set}) set_property(DIRECTORY PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}" ) else() message(FATAL_ERROR "Cannot set more than one TEST_INCLUDE_FILE" ) endif() endif() endfunction() ############################################################################### set(_DOCTEST_DISCOVER_TESTS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/DoctestAddTests.cmake ) quill-12.1.0/cmake/DoctestAddTests.cmake000066400000000000000000000100231522564103500200430ustar00rootroot00000000000000# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. set(prefix "${TEST_PREFIX}") set(suffix "${TEST_SUFFIX}") set(spec ${TEST_SPEC}) set(extra_args ${TEST_EXTRA_ARGS}) set(properties ${TEST_PROPERTIES}) set(add_labels ${TEST_ADD_LABELS}) set(junit_output_dir "${TEST_JUNIT_OUTPUT_DIR}") set(script) set(suite) set(tests) function(add_command NAME) set(_args "") foreach(_arg ${ARGN}) if(_arg MATCHES "[^-./:a-zA-Z0-9_]") set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument else() set(_args "${_args} ${_arg}") endif() endforeach() set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) endfunction() # Run test executable to get list of available tests if(NOT EXISTS "${TEST_EXECUTABLE}") message(FATAL_ERROR "Specified test executable '${TEST_EXECUTABLE}' does not exist" ) endif() if("${spec}" MATCHES .) set(spec "--test-case=${spec}") endif() execute_process( COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-cases OUTPUT_VARIABLE output RESULT_VARIABLE result WORKING_DIRECTORY "${TEST_WORKING_DIR}" ) if(NOT ${result} EQUAL 0) message(FATAL_ERROR "Error running test executable '${TEST_EXECUTABLE}':\n" " Result: ${result}\n" " Output: ${output}\n" ) endif() string(REPLACE "\n" ";" output "${output}") # Parse output foreach(line ${output}) if("${line}" STREQUAL "===============================================================================" OR "${line}" MATCHES [==[^\[doctest\] ]==]) continue() endif() set(test ${line}) set(labels "") if(${add_labels}) # get test suite that test belongs to execute_process( COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" --test-case=${test} --list-test-suites OUTPUT_VARIABLE labeloutput RESULT_VARIABLE labelresult WORKING_DIRECTORY "${TEST_WORKING_DIR}" ) if(NOT ${labelresult} EQUAL 0) message(FATAL_ERROR "Error running test executable '${TEST_EXECUTABLE}':\n" " Result: ${labelresult}\n" " Output: ${labeloutput}\n" ) endif() string(REPLACE "\n" ";" labeloutput "${labeloutput}") foreach(labelline ${labeloutput}) if("${labelline}" STREQUAL "===============================================================================" OR "${labelline}" MATCHES [==[^\[doctest\] ]==]) continue() endif() list(APPEND labels ${labelline}) endforeach() endif() if(NOT "${junit_output_dir}" STREQUAL "") # turn testname into a valid filename by replacing all special characters with "-" string(REGEX REPLACE "[/\\:\"|<>]" "-" test_filename "${test}") set(TEST_JUNIT_OUTPUT_PARAM "--reporters=junit" "--out=${junit_output_dir}/${prefix}${test_filename}${suffix}.xml") else() unset(TEST_JUNIT_OUTPUT_PARAM) endif() # use escape commas to handle properly test cases with commas inside the name string(REPLACE "," "\\," test_name ${test}) # ...and add to script add_command(add_test "${prefix}${test}${suffix}" ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" "--test-case=${test_name}" "${TEST_JUNIT_OUTPUT_PARAM}" ${extra_args} ) add_command(set_tests_properties "${prefix}${test}${suffix}" PROPERTIES WORKING_DIRECTORY "${TEST_WORKING_DIR}" ${properties} LABELS ${labels} ) unset(labels) list(APPEND tests "${prefix}${test}${suffix}") endforeach() # Create a list of all discovered tests, which users may use to e.g. set # properties on the tests add_command(set ${TEST_LIST} ${tests}) # Write CTest script file(WRITE "${CTEST_FILE}" "${script}")quill-12.1.0/cmake/FindSphinx.cmake000066400000000000000000000005651522564103500170660ustar00rootroot00000000000000#Look for an executable called sphinx-build find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable") include(FindPackageHandleStandardArgs) #Handle standard arguments to find_package like REQUIRED and QUIET find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)quill-12.1.0/cmake/QuillUtils.cmake000066400000000000000000000110421522564103500171130ustar00rootroot00000000000000include(CheckCXXSourceCompiles) # Get Quill version from include/quill/Version.h and store it as QUILL_VERSION function(quill_extract_version) file(READ "${CMAKE_CURRENT_LIST_DIR}/include/quill/Backend.h" file_contents) string(REGEX MATCH "constexpr uint32_t VersionMajor{([0-9]+)}" _ "${file_contents}") if (NOT CMAKE_MATCH_COUNT EQUAL 1) message(FATAL_ERROR "Failed to extract major version number from quill/Backend.h") endif () set(version_major ${CMAKE_MATCH_1}) string(REGEX MATCH "constexpr uint32_t VersionMinor{([0-9]+)}" _ "${file_contents}") if (NOT CMAKE_MATCH_COUNT EQUAL 1) message(FATAL_ERROR "Failed to extract minor version number from quill/Backend.h") endif () set(version_minor ${CMAKE_MATCH_1}) string(REGEX MATCH "constexpr uint32_t VersionPatch{([0-9]+)}" _ "${file_contents}") if (NOT CMAKE_MATCH_COUNT EQUAL 1) message(FATAL_ERROR "Failed to extract patch version number from quill/Backend.h") endif () set(version_patch ${CMAKE_MATCH_1}) set(QUILL_VERSION "${version_major}.${version_minor}.${version_patch}" PARENT_SCOPE) endfunction() # Define the function to set common compile options function(set_common_compile_options target_name) cmake_parse_arguments(COMPILE_OPTIONS "" "VISIBILITY" "" ${ARGN}) # Set default visibility to PRIVATE if not provided if (NOT DEFINED COMPILE_OPTIONS_VISIBILITY) set(COMPILE_OPTIONS_VISIBILITY PRIVATE) endif () target_compile_options(${target_name} ${COMPILE_OPTIONS_VISIBILITY} # General warnings for Clang, AppleClang, and GNU, but NOT on Windows $<$,$,$>,$>>: -Wall -Wextra -pedantic -Werror -Wredundant-decls -Wfloat-equal > # GCC-specific hardening and security flags $<$,$>: -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 > # GCC >= 7.1 specific: suppress PSABI warning $<$,$,7.1>>: -Wno-psabi > # Clang specific options, but NOT on Windows $<$,$>,$>>: -Wimplicit-int-float-conversion -Wdocumentation > # Disable C++20 extension warnings for Clang > 17, but NOT on Windows $<$,$,17>,$>>: -Wno-c++20-extensions > # Disable specific warning for Clang and AppleClang, but NOT on Windows $<$,$>,$>>: -Wno-gnu-zero-variadic-macro-arguments > # Windows-specific options $<$:$<$,$>:/bigobj /WX /W4>> ) if (QUILL_NO_EXCEPTIONS) # Add flags -fno-exceptions -fno-rtti to make sure we support them. # Note: for MSVC, /EHsc is stripped from CMAKE_CXX_FLAGS at the root # CMakeLists.txt scope (function-local string(REPLACE ...) would be a no-op). target_compile_options(${target_name} ${COMPILE_OPTIONS_VISIBILITY} $<$,$,$>: -fno-exceptions -fno-rtti> $<$:/wd4702 /GR- /EHs-c- /D_HAS_EXCEPTIONS=0>) else () # Additional MSVC specific options - only set for non-QUILL_NO_EXCEPTIONS builds target_compile_options(${target_name} ${COMPILE_OPTIONS_VISIBILITY} $<$:/EHsc>) endif () endfunction() function(check_cxx_atomics_available variable) set(SAVED_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") set(CMAKE_REQUIRED_LIBRARIES "") check_cxx_source_compiles(" #include #include std::atomic counter; int main() { uint64_t res = std::atomic_fetch_add(&counter, 1); return (int)res; }" ${variable}) set(CMAKE_REQUIRED_LIBRARIES "${SAVED_CMAKE_REQUIRED_LIBRARIES}") endfunction() quill-12.1.0/cmake/quill-config.cmake.in000066400000000000000000000002171522564103500200040ustar00rootroot00000000000000@PACKAGE_INIT@ find_package(Threads REQUIRED) include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake) check_required_components(quill)quill-12.1.0/cmake/quill.pc.in000066400000000000000000000003261522564103500160640ustar00rootroot00000000000000includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: quill Description: Low Latency C++ Logging Library URL: https://github.com/odygrd/quill Version: @QUILL_VERSION@ CFlags: -I${includedir} Libs: @QUILL_PTHREAD_LIBS@ quill-12.1.0/docs/000077500000000000000000000000001522564103500136545ustar00rootroot00000000000000quill-12.1.0/docs/CMakeLists.txt000066400000000000000000000045411522564103500164200ustar00rootroot00000000000000find_package(Doxygen REQUIRED) # Find all the public headers set(QUILL_HEADER_DIR "${CMAKE_SOURCE_DIR}/include/quill") file(GLOB_RECURSE QUILL_PUBLIC_HEADERS "${QUILL_HEADER_DIR}/*.h") set(DOXYGEN_INPUT_DIR ${QUILL_HEADER_DIR}) set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doxygen) set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml) set(DOXYGEN_TAG_FILE ${DOXYGEN_OUTPUT_DIR}/quill.tag) set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) #Replace variables inside @@ with the current values configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}) #Doxygen won't create this for us add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} ${DOXYGEN_TAG_FILE} DEPENDS ${QUILL_PUBLIC_HEADERS} COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} COMMENT "Generating docs") add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE} ${DOXYGEN_TAG_FILE}) find_package(Sphinx REQUIRED) set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx) set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html) set(SPHINX_TAG_FILE ${SPHINX_BUILD}/quill.tag) # Pick up every docs source automatically so adding a new .rst does not silently # skip the Sphinx rebuild trigger. CONFIGURE_DEPENDS makes CMake re-glob on build. file(GLOB SPHINX_RST_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.rst") # Only regenerate Sphinx when: # - Doxygen has rerun # - Our doc files have been updated # - The Sphinx config has been updated add_custom_command(OUTPUT ${SPHINX_INDEX_FILE} ${SPHINX_TAG_FILE} COMMAND ${SPHINX_EXECUTABLE} -b html # Tell Breathe where to find the Doxygen output -Dbreathe_projects.Quill=${DOXYGEN_OUTPUT_DIR}/xml ${SPHINX_SOURCE} ${SPHINX_BUILD} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DOXYGEN_TAG_FILE} ${SPHINX_TAG_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${SPHINX_RST_SOURCES} ${DOXYGEN_INDEX_FILE} ${DOXYGEN_TAG_FILE} MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py COMMENT "Generating documentation with Sphinx") # Nice named target so we can run the job easily add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE} ${SPHINX_TAG_FILE}) quill-12.1.0/docs/Doxyfile.in000066400000000000000000003351531522564103500160010ustar00rootroot00000000000000# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the configuration # file that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "My Project" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIR@" # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be # interpreted by doxygen. # The default value is: NO. JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # By default Python docstrings are displayed as preformatted text and doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the # doxygen's special commands can be used and the contents of the docstring # documentation blocks is shown as doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. # When you need a literal { or } or , in the value part of an alias you have to # escape them by means of a backslash (\), this can lead to conflicts with the # commands \{ and \} for these it is advised to use the version @{ and @} or use # a double escape (\\{ and \\}) ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice # sources only. Doxygen will then generate output that is more tailored for that # language. For instance, namespaces will be presented as modules, types will be # separated into more groups, etc. # The default value is: NO. OPTIMIZE_OUTPUT_SLICE = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 # The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which efficively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = YES # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If this flag is set to YES, the name of an unnamed parameter in a declaration # will be determined by the corresponding definition. By default unnamed # parameters remain unnamed in the output. # The default value is: YES. RESOLVE_UNNAMED_PARAMS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # With the correct setting of option CASE_SENSE_NAMES doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that # are not case sensitive the option should be be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. If # EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. # Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = "@DOXYGEN_INPUT_DIR@" # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), # *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, # *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.pyw \ *.f90 \ *.f95 \ *.f03 \ *.f08 \ *.f18 \ *.f \ *.for \ *.vhd \ *.vhdl \ *.ucf \ *.qsf \ *.ice # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = */include/quill/bundled/* */test/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for # which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. # CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to # YES then doxygen will add the directory of each input to the include path. # The default value is: YES. # CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. # CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the # path to the directory containing a file called compile_commands.json. This # file is the compilation database (see: # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the # options used when the source files were built. This is equivalent to # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To # create a documentation set, doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: # https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. # Possible values are: png (the default) and svg (looks nicer but requires the # pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. # The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /