Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/flow/builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <flow/common.hpp>
#include <flow/graph_builder.hpp>
#include <flow/impl.hpp>
#include <log/level.hpp>

#include <stdx/ct_string.hpp>

Expand Down
1 change: 1 addition & 0 deletions include/flow/graph_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <flow/common.hpp>
#include <flow/detail/walk.hpp>
#include <flow/impl.hpp>
#include <log/level.hpp>

#include <stdx/ct_string.hpp>
#include <stdx/cx_multimap.hpp>
Expand Down
9 changes: 7 additions & 2 deletions include/flow/impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ template <stdx::ct_string Name, std::size_t NumSteps> class impl {
namespace detail {
template <stdx::ct_string Name, auto... FuncPtrs> struct inlined_func_list {
constexpr static auto active = sizeof...(FuncPtrs) > 0;
constexpr static auto ct_name = Name;

__attribute__((flatten, always_inline)) auto operator()() const -> void {
constexpr static bool loggingEnabled = not Name.empty();
Expand All @@ -86,13 +87,17 @@ template <stdx::ct_string Name, auto... FuncPtrs> struct inlined_func_list {
stdx::ct_string_to_type<Name, sc::string_constant>();

if constexpr (loggingEnabled) {
CIB_TRACE("flow.start({})", name);
using log_spec_t = decltype(get_log_spec<inlined_func_list>());
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level,
"flow.start({})", name);
}

(FuncPtrs(), ...);

if constexpr (loggingEnabled) {
CIB_TRACE("flow.end({})", name);
using log_spec_t = decltype(get_log_spec<inlined_func_list>());
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level,
"flow.end({})", name);
}
}
};
Expand Down
32 changes: 32 additions & 0 deletions include/flow/log.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <log/log.hpp>

#include <type_traits>

namespace flow {
struct default_log_spec {
using flavor = logging::default_flavor_t;
constexpr static auto level = logging::level::TRACE;
};
template <stdx::ct_string, typename...>
constexpr auto log_spec = default_log_spec{};

template <typename T, typename... DummyArgs>
requires(sizeof...(DummyArgs) == 0)
constexpr static auto get_log_spec() {
if constexpr (std::is_same_v<decltype(log_spec<T::ct_name, DummyArgs...>),
default_log_spec const>) {
return log_spec<"default", DummyArgs...>;
} else {
return log_spec<T::ct_name, DummyArgs...>;
}
}

template <typename T, typename... DummyArgs, typename... Args>
auto log_with_spec(Args &&...args) {
using log_spec_t = decltype(get_log_spec<T, DummyArgs...>());
logging::log<typename log_spec_t::flavor, log_spec_t::level,
cib_log_module_id_t>(std::forward<Args>(args)...);
}
} // namespace flow
32 changes: 17 additions & 15 deletions include/flow/step.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#include <cib/detail/runtime_conditional.hpp>
#include <cib/func_decl.hpp>
#include <flow/common.hpp>
#include <flow/log.hpp>
#include <flow/subgraph_identity.hpp>
#include <log/log.hpp>
#include <sc/string_constant.hpp>

#include <stdx/compiler.hpp>
Expand All @@ -25,7 +25,7 @@ struct rt_node {

template <stdx::ct_string Type, stdx::ct_string Name,
subgraph_identity Identity, typename Cond, typename F>
struct ct_node : rt_node {
struct ct_node {
using is_subgraph = void;
using type_t =
decltype(stdx::ct_string_to_type<Type, sc::string_constant>());
Expand All @@ -39,19 +39,21 @@ struct ct_node : rt_node {

constexpr static auto condition = Cond{};

constexpr static auto run_func = [] {
if (condition) {
F{}();
}
};

constexpr static auto log_func = [] {
if (condition) {
CIB_TRACE("flow.{}({})", type_t{}, name_t{});
}
};

constexpr ct_node() : rt_node{+run_func, +log_func} {}
constexpr operator rt_node() const {
return rt_node{
[] {
if (condition) {
F{}();
}
},
[] {
if (condition) {
using log_spec_t = decltype(get_log_spec<ct_node>());
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level,
"flow.{}({})", type_t{}, name_t{});
}
}};
}

constexpr auto operator*() const {
if constexpr (Identity == subgraph_identity::REFERENCE) {
Expand Down
2 changes: 1 addition & 1 deletion test/flow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ else()
warnings
cib)

add_tests(flow logging)
add_tests(flow logging log_levels custom_log_levels)
endif()

add_tests(graph graph_builder)
Expand Down
83 changes: 83 additions & 0 deletions test/flow/custom_log_levels.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <cib/cib.hpp>
#include <flow/flow.hpp>

#include <catch2/catch_test_macros.hpp>

#include <string>
#include <vector>

namespace {
using namespace flow::literals;

template <auto... Cs> struct wrapper {
struct inner {
constexpr static auto config = cib::config(Cs...);
};
constexpr static auto n = cib::nexus<inner>{};

wrapper() { n.init(); }

template <typename S> static auto run() -> void { n.template service<S>(); }
};

std::vector<logging::level> log_calls{};

template <typename S, auto... Cs>
constexpr auto run_flow = []() -> void {
log_calls.clear();
wrapper<Cs...>::template run<S>();
};

struct TestFlowA : public flow::service<"A"> {};
struct TestFlowB : public flow::service<"B"> {};

constexpr auto msA = flow::milestone<"msA">();
constexpr auto msB = flow::milestone<"msB">();

struct log_config {
struct log_handler {
template <logging::level Level, typename ModuleId,
typename FilenameStringType, typename LineNumberType,
typename MsgType>
auto log(FilenameStringType, LineNumberType, MsgType const &) -> void {
log_calls.push_back(Level);
}
};
log_handler logger;
};
} // namespace

template <> inline auto logging::config<> = log_config{};

struct user1_log_spec : flow::default_log_spec {
constexpr static auto level = logging::level::USER1;
};
struct user2_log_spec : flow::default_log_spec {
constexpr static auto level = logging::level::USER2;
};
struct info_log_spec : flow::default_log_spec {
constexpr static auto level = logging::level::INFO;
};
template <> constexpr auto flow::log_spec<"default"> = info_log_spec{};

TEST_CASE("override default log level", "[flow_custom_log_levels]") {
run_flow<TestFlowA, cib::exports<TestFlowA>,
cib::extend<TestFlowA>(*msA)>();

REQUIRE(not log_calls.empty());
std::for_each(std::begin(log_calls), std::end(log_calls),
[](auto level) { CHECK(level == logging::level::INFO); });
}

template <> constexpr auto flow::log_spec<"B"> = user1_log_spec{};
template <> constexpr auto flow::log_spec<"msB"> = user2_log_spec{};

TEST_CASE("override log level by name", "[flow_custom_log_levels]") {
run_flow<TestFlowB, cib::exports<TestFlowB>,
cib::extend<TestFlowB>(*msB)>();

REQUIRE(log_calls.size() == 3);
CHECK(log_calls[0] == logging::level::USER1);
CHECK(log_calls[1] == logging::level::USER2);
CHECK(log_calls[2] == logging::level::USER1);
}
57 changes: 57 additions & 0 deletions test/flow/log_levels.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <cib/cib.hpp>
#include <flow/flow.hpp>

#include <catch2/catch_test_macros.hpp>

#include <string>
#include <vector>

namespace {
using namespace flow::literals;

template <auto... Cs> struct wrapper {
struct inner {
constexpr static auto config = cib::config(Cs...);
};
constexpr static auto n = cib::nexus<inner>{};

wrapper() { n.init(); }

template <typename S> static auto run() -> void { n.template service<S>(); }
};

std::vector<logging::level> log_calls{};

template <typename S, auto... Cs>
constexpr auto run_flow = []() -> void {
log_calls.clear();
wrapper<Cs...>::template run<S>();
};

struct NamedTestFlow : public flow::service<"TestFlow"> {};

constexpr auto ms = flow::milestone<"ms">();

struct log_config {
struct log_handler {
template <logging::level Level, typename ModuleId,
typename FilenameStringType, typename LineNumberType,
typename MsgType>
auto log(FilenameStringType, LineNumberType, MsgType const &) -> void {
log_calls.push_back(Level);
}
};
log_handler logger;
};
} // namespace

template <> inline auto logging::config<> = log_config{};

TEST_CASE("flow logs at TRACE by default", "[flow_log_levels]") {
run_flow<NamedTestFlow, cib::exports<NamedTestFlow>,
cib::extend<NamedTestFlow>(*ms)>();

REQUIRE(not log_calls.empty());
std::for_each(std::begin(log_calls), std::end(log_calls),
[](auto level) { CHECK(level == logging::level::TRACE); });
}