Skip to content

Commit

Permalink
added option to disable exceptions, add backend worker error handler,…
Browse files Browse the repository at this point in the history
… rename QUILL_RDTSC_CLOCK.

Fixes #16
Fixes #21
  • Loading branch information
odygrd committed Apr 25, 2020
1 parent 6d43c9d commit 27c10d7
Show file tree
Hide file tree
Showing 39 changed files with 452 additions and 101 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
- [v1.2.3](#v1.3.0)
- [v1.2.3](#v1.2.3)
- [v1.2.2](#v1.2.2)
- [v1.2.1](#v1.2.1)
- [v1.2.0](#v1.2.0)
- [v1.1.0](#v1.1.0)
- [v1.0.0](#v1.0.0)

## v1.3.0
* Added option `QUILL_NO_EXCEPTIONS` to disables exceptions, std::abort() is called instead. ([#16](https://github.com/odygrd/quill/issues/16))
* When exceptions are enabled any exception 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))
* `QUILL_RDTSC_CLOCK` is replaced by `QUILL_CHRONO_CLOCK` which is by default OFF.

## v1.2.3
* CMake changes to support package installation in conan.

Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ project(my_project)
#-------------------------------------------------------------------------------------------------------
# Options
#-------------------------------------------------------------------------------------------------------
option(QUILL_NO_EXCEPTIONS "Build without exceptions with -fno-exceptions flag" OFF)

option(QUILL_BUILD_EXAMPLES "Build the examples" OFF)

option(QUILL_BUILD_TESTS "Build the tests (Requires https://github.com/google/googletest to be installed)" OFF)
Expand Down Expand Up @@ -110,6 +112,10 @@ endif ()
#-------------------------------------------------------------------------------------------------------
# Additional Compiler Options
#-------------------------------------------------------------------------------------------------------
if (QUILL_NO_EXCEPTIONS)
add_definitions(-DQUILL_NO_EXCEPTIONS)
endif ()

# address sanitizer flags
if (QUILL_SANITIZE_ADDRESS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g")
Expand Down
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
add_executable(example_configure_backend example_configure_backend.cpp)
target_link_libraries(example_configure_backend quill)

add_executable(example_trivial example_trivial.cpp)
target_link_libraries(example_trivial quill)

Expand Down
28 changes: 28 additions & 0 deletions examples/example_configure_backend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Using std::chrono clock instead of the default rdtsc clock
*/
#define QUILL_CHRONO_CLOCK

#include "quill/Quill.h"
#include <iostream>

/**
* Test with random configuration options for the backend thread
* @return
*/

int main()
{
// Set a custom error handler to handler exceptions
quill::set_backend_worker_error_handler([](std::string const& s) { std::cout << s << std::endl; });

// Setting to an invalid CPU. When we call quill::start() our error handler will be invoked and an error will be logged
quill::config::set_backend_thread_cpu_affinity(static_cast<uint16_t>(321312));

quill::config::set_backend_thread_name("example_thread");

// Start the logging backend thread
quill::start();

LOG_INFO(quill::get_logger(), "{} {}", "Hello", "World!");
}
5 changes: 0 additions & 5 deletions examples/example_logging_to_file.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/**
* Using std::chrono clock instead of the default rdtsc clock
*/
#define QUILL_RDTSC_CLOCK 0

#include "quill/Quill.h"

static char const* filename = "example_filehandler.log";
Expand Down
7 changes: 7 additions & 0 deletions quill/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ set(HEADER_FILES
include/quill/LogLevel.h
include/quill/PatternFormatter.h
include/quill/Quill.h
include/quill/QuillError.h
include/quill/TweakMe.h
include/quill/Utility.h
include/quill/Version.h
Expand Down Expand Up @@ -106,6 +107,12 @@ add_library(${TARGET_NAME} STATIC "")

add_library(${TARGET_NAME}::${TARGET_NAME} ALIAS ${TARGET_NAME})

if (QUILL_NO_EXCEPTIONS)
if (NOT MSVC)
target_compile_options(${TARGET_NAME} PRIVATE -fno-exceptions)
endif ()
endif ()

# Add target sources
target_sources(${TARGET_NAME} PRIVATE ${SOURCE_FILES} ${HEADER_FILES})

Expand Down
2 changes: 1 addition & 1 deletion quill/include/quill/Fmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#pragma once

#include "TweakMe.h"
#include "quill/TweakMe.h"

/**
* Include a bundled header-only copy of lib fmt or an external one.
Expand Down
17 changes: 11 additions & 6 deletions quill/include/quill/PatternFormatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#pragma once

#include "quill/Fmt.h"
#include "quill/QuillError.h"
#include "quill/bundled/invoke/invoke.h"
#include "quill/detail/TimestampFormatter.h"
#include "quill/detail/misc/Attributes.h"
Expand All @@ -14,6 +15,7 @@
#include "quill/detail/misc/TypeTraits.h"
#include "quill/detail/misc/Utilities.h"
#include "quill/detail/record/StaticLogRecordInfo.h"

#include <chrono>
#include <cstdint>
#include <functional>
Expand Down Expand Up @@ -162,7 +164,7 @@ class PatternFormatter
* @param timezone The timezone of the timestamp, local_time or gmt_time
*/
template <typename TConstantString>
PatternFormatter(TConstantString format_pattern, std::string timestamp_format, Timezone timezone)
PatternFormatter(TConstantString format_pattern, std::string const& timestamp_format, Timezone timezone)
: _timestamp_formatter(timestamp_format, timezone)
{
_set_pattern(format_pattern);
Expand Down Expand Up @@ -298,6 +300,8 @@ class PatternFormatter
* %(thread) - Thread ID
* %(process) - Process ID
*
* @throws on invalid format string
*
* @tparam TConstantString a format string. Must be passed using the macro QUILL_STRING("format string");
*/
template <typename TConstantString>
Expand All @@ -320,6 +324,7 @@ class PatternFormatter
/**
* Process part of the pattern and create a helper formatter class
* @param format_pattern_part format pattern part
* @throws on invalid input
* @return a formater helper base
*/
template <size_t N>
Expand All @@ -341,10 +346,10 @@ class PatternFormatter

/**
* Given a part of the pattern modify it to match the expected lib fmt format
* @param pattern pattern
* @return formatted pattern to match the expected lib fmt format
*/
QUILL_NODISCARD std::string _generate_fmt_format_string(std::string pattern);
* @param pattern pattern
* @return formatted pattern to match the expected lib fmt format
*/
QUILL_NODISCARD static std::string _generate_fmt_format_string(std::string pattern);

private:
/** Formatters for any user's custom pattern - Important they have to be destructed last so they are defined first **/
Expand Down Expand Up @@ -477,7 +482,7 @@ void PatternFormatter::_set_pattern(TConstantString)
size_t const message_found = pattern.find("%(message)");
if (message_found == std::string::npos)
{
throw std::runtime_error("%(message) is required in the format pattern");
QUILL_THROW(QuillError{"%(message) is required in the format pattern"});
}

// break down the pattern to three parts, we can ignore part_2 which will be '%(message)'
Expand Down
18 changes: 18 additions & 0 deletions quill/include/quill/Quill.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ namespace quill
*/
QUILL_ATTRIBUTE_COLD void preallocate();

/**
* The background thread in very rare occasion might thrown an exception which can not be caught in the
* user threads. In that case the backend worker thread will call this callback instead.
*
* Set up a custom error handler to be used if the backend thread has any error.
*
* If no error handler is set, the default one will print to std::cerr.
*
* @note Not used when QUILL_NO_EXCEPTIONS is enabled.
*
* @note Must be called before quill::start();
*
* @param error_handler an error handler callback e.g [](std::string const& s) { std::cerr << s << std::endl; }
*
* @throws exception if it is called after the thread has started
*/
QUILL_ATTRIBUTE_COLD void set_backend_worker_error_handler(backend_worker_error_handler_t backend_worker_error_handler);

/**
* Starts the backend thread to write the logs to the handlers
* @throws When the backend thread fails to start
Expand Down
58 changes: 58 additions & 0 deletions quill/include/quill/QuillError.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors.
* Distributed under the MIT License (http://opensource.org/licenses/MIT)
*/

#pragma once

#include "quill/TweakMe.h"

#include "quill/detail/misc/Macros.h"
#include <exception>
#include <string>

#if defined(QUILL_NO_EXCEPTIONS)
#define QUILL_TRY if (true)
#define QUILL_THROW(ex) QUILL_REQUIRE(false, ex.what())
#define QUILL_CATCH(x) if (false)
#define QUILL_CATCH_ALL() if (false)
#else
#define QUILL_TRY try
#define QUILL_THROW(ex) throw(ex)
#define QUILL_CATCH(x) catch (x)
#define QUILL_CATCH_ALL() catch (...)
#endif

namespace quill
{
/**
* custom exception
*/
class QuillError : public std::exception
{
public:
explicit QuillError(std::string s) : _error(std::move(s)) {}
explicit QuillError(char const* s) : _error(s) {}

QuillError(QuillError const& other) noexcept : _error(other._error) {}

QuillError& operator=(const QuillError& other) noexcept
{
// check for self-assignment
if (&other == this)
{
return *this;
}
_error = other._error;
return *this;
}

~QuillError() override = default;

char const* what() const noexcept override { return _error.data(); }

private:
std::string _error;
};

} // namespace quill
28 changes: 19 additions & 9 deletions quill/include/quill/TweakMe.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
*/

/**
* If QUILL_RDTSC_CLOCK value is set to 0, Quill will use chrono system_clock for timestamps.
* If QUILL_CHRONO_CLOCK value is defined, Quill will use chrono system_clock for timestamps.
*
* QUILL_TSC_CLOCK mode :
* QUILL RDTSC CLOCK mode :
*
* TSC clock gives better performance on the caller thread. However, the initialisation time of the application is higher as
* we have to take multiple samples in the beginning to convert TSC to nanoseconds
Expand All @@ -38,17 +38,18 @@
* @note: This should be switchable even after quill is already installed as a static or shared library.
*
* Usage:
* Run cmake as e.g: cmake . -DCMAKE_CXX_FLAGS="-DQUILL_RDTSC_CLOCK=0"
* Usage:
* Run cmake as e.g: cmake . -DCMAKE_CXX_FLAGS="-DQUILL_CHRONO_CLOCK=1"
* or
* In the root CMake file use: `add_definitions(-DQUILL_RDTSC_CLOCK=0)`
* In the root CMake file use: `add_definitions(-DQUILL_CHRONO_CLOCK=1)`
*
* By default QUILL_RDTSC_CLOCK is set to 1
* By default RDTSC clock is enabled
*/
// #define QUILL_RDTSC_CLOCK 1
// #define QUILL_CHRONO_CLOCK

/**
* This option is only applicable if the RDTSC clock is enabled.
* When QUILL_RDTSC_CLOCK is not defined this option can be ignored
* When QUILL_CHRONO_CLOCK is defined this option can be ignored
*
* This value controls how frequently the backend thread will re-calculate and sync the TSC by
* getting the system time from the system wall clock.
Expand Down Expand Up @@ -84,8 +85,12 @@
*/
// #define QUILL_ACTIVE_LOG_LEVEL QUILL_LOG_LEVEL_TRACE_L3

/**************************************************************************************************/
/* Anything after this point requires the whole library to be recompiled with the desired option. */
/**************************************************************************************************/

/**
* Uses a custom copy of the fmt library instead of quill's bundled copy.
* Uses an installed version of the fmt library instead of quill's bundled copy.
* In this case quill will try to include <fmt/format.h> so make sure to set -I directories
* accordingly if not using CMake.
*
Expand All @@ -95,4 +100,9 @@
* Quill will look for a CMake Target with name `fmt`. If the target is not found it will
* use find_package(fmt REQUIRED) so make sure that fmt library is installed in your system
*/
// #define QUILL_FMT_EXTERNAL
// #define QUILL_FMT_EXTERNAL

/**
* Disables all exceptions and replaces them with std::abort()
*/
// #define QUILL_NO_EXCEPTIONS
4 changes: 2 additions & 2 deletions quill/include/quill/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#pragma once

#define QUILL_VERSION_MAJOR 1
#define QUILL_VERSION_MINOR 2
#define QUILL_VERSION_PATCH 3
#define QUILL_VERSION_MINOR 3
#define QUILL_VERSION_PATCH 0

#define QUILL_VERSION \
(QUILL_VERSION_MAJOR * 10000 + QUILL_VERSION_MINOR * 100 + QUILL_VERSION_PATCH)
Loading

0 comments on commit 27c10d7

Please sign in to comment.