Skip to content

Commit

Permalink
Improve compile time string view logging levels
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanel committed Oct 27, 2023
1 parent 90f37b7 commit 6669103
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 70 deletions.
30 changes: 21 additions & 9 deletions src/engine/include/coincenteroptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "exchangeinfomap.hpp"
#include "exchangepublicapi.hpp"
#include "loadconfiguration.hpp"
#include "logginginfo.hpp"
#include "static_string_view_helpers.hpp"
#include "staticcommandlineoptioncheck.hpp"
#include "stringhelpers.hpp"
Expand All @@ -34,6 +35,22 @@ struct CoincenterCmdLineOptions {
static constexpr int64_t kDefaultRepeatDurationSeconds =
std::chrono::duration_cast<TimeInS>(kDefaultRepeatTime).count();

static constexpr std::string_view kLogValue1 = "<levelName|0-";
static constexpr std::string_view kLogValue =
JoinStringView_v<kLogValue1, IntToStringView_v<LoggingInfo::kNbLogLevels - 1U>, CharToStringView_v<'>'>>;

static constexpr std::string_view kLoggingLevelsSep = "|";
static constexpr std::string_view kLoggingLevels =
make_joined_string_view<kLoggingLevelsSep, LoggingInfo::kLogLevelNames>::value;

static constexpr std::string_view kLog1 =
"Sets the log level in the console during all execution. "
"Possible values are: (";
static constexpr std::string_view kLog2 = ") or (0-";
static constexpr std::string_view kLog3 = ") (overrides .log.console in general config file)";
static constexpr std::string_view kLog =
JoinStringView_v<kLog1, kLoggingLevels, kLog2, IntToStringView_v<LoggingInfo::kNbLogLevels>, kLog3>;

static constexpr std::string_view kOutput1 = "Output format. One of (";
static constexpr std::string_view kOutput2 = ") (default configured in general config file)";
static constexpr std::string_view kOutput =
Expand Down Expand Up @@ -221,18 +238,13 @@ struct CoincenterAllowedOptions {
static constexpr CommandLineOptionWithValue value[] = {
{{{"General", 100}, "help", 'h', "", "Display this information"}, &OptValueType::help},
{{{"General", 200}, "--data", "<path/to/data>", CoincenterCmdLineOptions::kData}, &OptValueType::dataDir},
{{{"General", 300},
"--log",
'v',
"<levelName|0-6>",
"Sets the log level in the console during all execution. "
"Possible values are: (off|critical|error|warning|info|debug|trace) or "
"(0-6) (overrides .log.console in general config file)"},
{{{"General", 300}, "--log", 'v', CoincenterCmdLineOptions::kLogValue, CoincenterCmdLineOptions::kLog},
&OptValueType::logConsole},
{{{"General", 400}, "--log-console", CoincenterCmdLineOptions::kLogValue, "Synonym of --log"},
&OptValueType::logConsole},
{{{"General", 400}, "--log-console", "<levelName|0-6>", "Synonym of --log"}, &OptValueType::logConsole},
{{{"General", 400},
"--log-file",
"<levelName|0-6>",
CoincenterCmdLineOptions::kLogValue,
"Sets the log level in files during all execution (overrides .log.file in general config file). "
"Number of rotating files to keep and their size is configurable in the general config file"},
&OptValueType::logFile},
Expand Down
2 changes: 1 addition & 1 deletion src/monitoring/src/prometheusmetricgateway.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ PrometheusMetricGateway::~PrometheusMetricGateway() {
// We should not throw in a destructor - catch any exception and do nothing, not even a log (it could throw)
try {
flush();
} catch (const std::exception&) {
} catch (const std::exception&) { // NOLINT(bugprone-empty-catch)
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/objects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ add_unit_test(
CCT_DISABLE_SPDLOG
)

add_unit_test(
parseloglevel_test
src/parseloglevel.cpp
test/parseloglevel_test.cpp
LIBRARIES
coincenter_tech
DEFINITIONS
CCT_DISABLE_SPDLOG
)

add_unit_test(
wallet_test
test/wallet_test.cpp
Expand Down
3 changes: 3 additions & 0 deletions src/objects/include/logginginfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class LoggingInfo {
static constexpr char const *const kOutputLoggerName = "output";
static constexpr std::string_view kJsonFieldConsoleLevelName = "consoleLevel";
static constexpr std::string_view kJsonFieldFileLevelName = "fileLevel";
static constexpr std::string_view kLogLevelNames[] = {"off", "critical", "error", "warning",
"info", "debug", "trace"};
static constexpr auto kNbLogLevels = std::size(kLogLevelNames);

enum class WithLoggersCreation : int8_t { kNo, kYes };

Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/objects/src/logginginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <string_view>
#include <utility>

#include "cct_exception.hpp"
#include "cct_fixedcapacityvector.hpp"
#include "cct_json.hpp"
#include "cct_log.hpp"
Expand Down
35 changes: 35 additions & 0 deletions src/objects/src/parseloglevel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "parseloglevel.hpp"

#include <cstdint>
#include <string_view>
#include <type_traits>

#include "cct_exception.hpp"
#include "logginginfo.hpp"
#include "static_string_view_helpers.hpp"

namespace cct {
int8_t LogPosFromLogStr(std::string_view logStr) {
if (logStr.size() == 1) {
const int8_t logLevelPos = logStr.front() - '0';
if (logLevelPos < 0 ||
logLevelPos >= static_cast<std::remove_const_t<decltype(logLevelPos)>>(LoggingInfo::kNbLogLevels)) {
throw exception("Unrecognized log level {}. Possible values are [0-{}]", logStr,
'0' + (LoggingInfo::kNbLogLevels - 1U));
}
return logLevelPos;
}

int8_t logLevel = 0;
for (const auto logName : LoggingInfo::kLogLevelNames) {
if (logStr == logName) {
return logLevel;
}
++logLevel;
}

static constexpr std::string_view kPrintLogNameSep = "|";
throw exception("Unrecognized log level name {}. Possible values are {}", logStr,
make_joined_string_view<kPrintLogNameSep, LoggingInfo::kLogLevelNames>::value);
}
} // namespace cct
File renamed without changes.
8 changes: 0 additions & 8 deletions src/tech/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,6 @@ add_unit_test(
test/mathhelpers_test.cpp
)

add_unit_test(
parseloglevel_test
src/parseloglevel.cpp
test/parseloglevel_test.cpp
DEFINITIONS
CCT_DISABLE_SPDLOG
)

add_unit_test(
simpletable_test
src/simpletable.cpp
Expand Down
72 changes: 63 additions & 9 deletions src/tech/include/static_string_view_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,21 @@
namespace cct {

/// Concatenates variadic template std::string_view arguments at compile time and defines a std::string_view pointing on
/// a static storage. The storage is guaranteed to be null terminated.
/// a static storage. The storage is guaranteed to be null terminated (but not itself included in the returned value)
/// Adapted from
/// https://stackoverflow.com/questions/38955940/how-to-concatenate-static-strings-at-compile-time/62823211#62823211
template <std::string_view const&... Strs>
class JoinStringView {
private:
// Join all strings into a single std::array of chars
static constexpr auto impl() noexcept {
constexpr std::size_t len = (Strs.size() + ... + 0);
std::array<char, len + 1> arr{};
constexpr std::string_view::size_type len = (Strs.size() + ... + 0);
std::array<char, len + 1U> arr; // +1 for null terminated char
if constexpr (len > 0) {
auto append = [i = 0, &arr](auto const& s) mutable {
for (auto c : s) arr[i++] = c;
};
auto append = [it = arr.begin()](auto const& s) mutable { it = std::copy(s.begin(), s.end(), it); };
(append(Strs), ...);
}
arr[len] = 0;
arr.back() = '\0';
return arr;
}
// Give the joined string static storage
Expand All @@ -35,12 +33,68 @@ class JoinStringView {
public:
// View as a std::string_view
static constexpr std::string_view value{arr.data(), arr.size() - 1};

// c_str version (null-terminated)
static constexpr const char* const c_str = arr.data();
};

// Helper to get the value out
template <std::string_view const&... Strs>
static constexpr auto JoinStringView_v = JoinStringView<Strs...>::value;

/// Same as JoinStringView but with a char separator between each string_view
template <std::string_view const& Sep, std::string_view const&... Strs>
class JoinStringViewWithSep {
private:
// Join all strings into a single std::array of chars
static constexpr auto impl() noexcept {
constexpr std::string_view::size_type len = (Strs.size() + ... + 0);
constexpr auto nbSv = sizeof...(Strs);
std::array<char, std::max(len + 1U + ((nbSv == 0U ? 0U : (nbSv - 1U)) * Sep.size()),
static_cast<std::string_view::size_type>(1))>
arr;
if constexpr (len > 0) {
auto append = [it = arr.begin(), &arr](auto const& s) mutable {
if (it != arr.begin()) {
it = std::copy(Sep.begin(), Sep.end(), it);
}
it = std::copy(s.begin(), s.end(), it);
};
(append(Strs), ...);
}
arr.back() = '\0';
return arr;
}
// Give the joined string static storage
static constexpr auto arr = impl();

public:
// View as a std::string_view
static constexpr std::string_view value{arr.data(), arr.size() - 1};

// c_str version (null-terminated)
static constexpr const char* const c_str = arr.data();
};

// Helper to get the value out
template <std::string_view const& Sep, std::string_view const&... Strs>
static constexpr auto JoinStringViewWithSep_v = JoinStringViewWithSep<Sep, Strs...>::value;

namespace details {
template <std::string_view const& Sep, const auto& a, typename>
struct make_joined_string_view_impl;

template <std::string_view const& Sep, const auto& a, std::size_t... i>
struct make_joined_string_view_impl<Sep, a, std::index_sequence<i...>> {
static constexpr auto value = JoinStringViewWithSep<Sep, a[i]...>::value;
};

} // namespace details

// make joined string view from array like value
template <std::string_view const& Sep, const auto& a>
using make_joined_string_view = details::make_joined_string_view_impl<Sep, a, std::make_index_sequence<std::size(a)>>;

/// Converts an integer value to its string_view representation at compile time.
/// The underlying storage is not null terminated.
template <int64_t intVal>
Expand Down Expand Up @@ -79,10 +133,10 @@ static constexpr auto IntToStringView_v = IntToStringView<intVal>::value;
template <char Char>
class CharToStringView {
private:
static constexpr char c = Char;
static constexpr char ch = Char;

public:
static constexpr std::string_view value{&c, 1};
static constexpr std::string_view value{&ch, 1};
};

template <char Char>
Expand Down
42 changes: 0 additions & 42 deletions src/tech/src/parseloglevel.cpp

This file was deleted.

17 changes: 16 additions & 1 deletion src/tech/test/static_string_view_helpers_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <string_view>

namespace cct {
// JoinStringView
namespace test1 {
static_assert(JoinStringView_v<>.empty());
} // namespace test1
Expand Down Expand Up @@ -40,9 +39,25 @@ static constexpr std::string_view kStr4 = "in my bag";
static_assert(JoinStringView_v<kStr1, IntToStringView_v<70>, kStr2, IntToStringView_v<1894>, kStr3, kStr4> ==
"I have 70 oranges and 1894 bananas in my bag");
} // namespace test5
namespace test6 {
static constexpr std::string_view kSep = "|";
static constexpr std::string_view kStr1 = "apples";
static constexpr std::string_view kStr2 = "bananas";
static constexpr std::string_view kStr3 = "oranges";
static constexpr std::string_view kStr4 = "blueberries";
static constexpr std::string_view kStr5 = "strawberries";

static_assert(JoinStringViewWithSep_v<kSep, kStr1, kStr2, kStr3, kStr4, kStr5> ==
"apples|bananas|oranges|blueberries|strawberries");

static constexpr std::string_view kStrArr[] = {"apples", "bananas", "oranges", "blueberries", "strawberries"};

static_assert(make_joined_string_view<kSep, kStrArr>::value == "apples|bananas|oranges|blueberries|strawberries");
} // namespace test6

// IntToStringView
static_assert(IntToStringView_v<0> == "0");
static_assert(IntToStringView_v<37> == "37");
static_assert(IntToStringView_v<-1273006> == "-1273006");

} // namespace cct

0 comments on commit 6669103

Please sign in to comment.