Skip to content

Feature/SE integration #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
.idea

/build
/build-ex
/cmake-build-*

/.build
Expand Down
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API ON)

project(cpp-jam
VERSION 0.0.1
Expand All @@ -40,6 +41,12 @@ find_package(Boost.DI CONFIG REQUIRED)
find_package(qtils CONFIG REQUIRED)
find_package(prometheus-cpp CONFIG REQUIRED)

if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-fmodules-ts)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
add_compile_options(-fmodules)
endif()

add_library(headers INTERFACE)
target_include_directories(headers INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src_>
Expand Down
2 changes: 2 additions & 0 deletions example/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
general:
name: NameFromConfig
base_path: /tmp/jam_node
modules_dir: modules

metrics:
enabled: true
Expand Down
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ add_subdirectory(metrics)
# Clocks and time subsystem
add_subdirectory(clock)

# Subscription Engine subsystem
add_subdirectory(se)

# Modules subsystem
add_subdirectory(modules)
4 changes: 3 additions & 1 deletion src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ add_library(build_version

add_library(app_configuration SHARED configuration.cpp)
target_link_libraries(app_configuration
Boost::boost)
Boost::boost
fmt::fmt
)

add_library(app_configurator SHARED configurator.cpp)
target_link_libraries(app_configurator
Expand Down
8 changes: 8 additions & 0 deletions src/app/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ namespace jam::app {
return name_;
}

std::filesystem::path Configuration::basePath() const {
return base_path_;
}

std::filesystem::path Configuration::modulesDir() const {
return modules_dir_;
}

std::optional<Configuration::Endpoint> Configuration::metricsEndpoint()
const {
return metrics_endpoint_;
Expand Down
6 changes: 6 additions & 0 deletions src/app/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <string>

#include <filesystem>
#include <boost/asio/ip/tcp.hpp>
#include <utils/ctor_limiters.hpp>

Expand All @@ -22,13 +23,18 @@ namespace jam::app {

[[nodiscard]] std::string nodeVersion() const;
[[nodiscard]] std::string nodeName() const;
[[nodiscard]] std::filesystem::path basePath() const;
[[nodiscard]] std::filesystem::path modulesDir() const;

[[nodiscard]] std::optional<Endpoint> metricsEndpoint() const;

private:
friend class Configurator; // for external configure

std::string version_;
std::string name_;
std::filesystem::path base_path_;
std::filesystem::path modules_dir_;

Endpoint metrics_endpoint_;
std::optional<bool> metrics_enabled_;
Expand Down
117 changes: 98 additions & 19 deletions src/app/configurator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include "app/configuration.hpp"
#include "app/configurator.hpp"

#include <filesystem>
#include <iostream>

#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/value_semantic.hpp>
#include <qtils/outcome.hpp>
#include <qtils/strict_sptr.hpp>

#include "app/build_version.hpp"
#include "app/configurator.hpp"

#include <boost/beast/core/error.hpp>
#include "app/configuration.hpp"

using Endpoint = boost::asio::ip::tcp::endpoint;

Expand All @@ -27,6 +27,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(jam::app, Configurator::Error, e) {
return "CLI Arguments parse failed";
case E::ConfigFileParseFailed:
return "Config file parse failed";
case E::InvalidValue:
return "Result config has invalid values";
}
BOOST_UNREACHABLE_RETURN("Unknown log::Error");
}
Expand Down Expand Up @@ -84,23 +86,25 @@ namespace jam::app {

po::options_description general_options("General options", 120, 100);
general_options.add_options()
("help,h", "show this help message")
("version,v", "show version information")
("name,n", po::value<std::string>(), "set name of node")
("config,c", po::value<std::string>(), "optional, filepath to load configuration from. Overrides default config values")
("help,h", "Show this help message")
("version,v", "Show version information")
("base_path", po::value<std::string>(), "Set base path. All relative paths will be resolved based on this path.")
("config,c", po::value<std::string>(), "Optional. Filepath to load configuration from. Overrides default configuration values.")
("name,n", po::value<std::string>(), "Set name of node")
("log,l", po::value<std::vector<std::string>>(),
"Sets a custom logging filter.\n"
"Syntax is `<target>=<level>`, e.g. -llibp2p=off.\n"
"Log levels (most to least verbose) are trace, debug, verbose, info, warn, error, critical, off.\n"
"By default, all targets log `info`.\n"
"The global log level can be set with -l<level>.")
"Syntax: <target>=<level>, e.g., -llibp2p=off.\n"
"Log levels: trace, debug, verbose, info, warn, error, critical, off.\n"
"Default: all targets log at `info`.\n"
"Global log level can be set with: -l<level>.")
("modules_dir", po::value<std::string>(), "Set path to modules directory.")
;

po::options_description metrics_options("Metric options");
metrics_options.add_options()
("prometheus-disable", "set to disable OpenMetrics")
("prometheus-host", po::value<std::string>(), "address for OpenMetrics over HTTP")
("prometheus-port", po::value<uint16_t>(), "port for OpenMetrics over HTTP")
("prometheus-disable", "Set to disable OpenMetrics")
("prometheus-host", po::value<std::string>(), "Set address for OpenMetrics over HTTP")
("prometheus-port", po::value<uint16_t>(), "Set port for OpenMetrics over HTTP")
;

// clang-format on
Expand All @@ -110,7 +114,7 @@ namespace jam::app {
.add(metrics_options);
}

outcome::result<bool> Configurator::step1() {
outcome::result<bool> Configurator::step1() { // read min cli-args and config
namespace po = boost::program_options;
namespace fs = std::filesystem;

Expand All @@ -120,7 +124,7 @@ namespace jam::app {

po::variables_map vm;

// first-run parse to read only general options and to lookup for "help",
// first-run parse to read-only general options and to lookup for "help",
// "config" and "version". all the rest options are ignored
try {
po::parsed_options parsed = po::command_line_parser(argc_, argv_)
Expand Down Expand Up @@ -192,14 +196,16 @@ namespace jam::app {
}

outcome::result<std::shared_ptr<Configuration>> Configurator::calculateConfig(
std::shared_ptr<soralog::Logger> logger) {
qtils::StrictSharedPtr<soralog::Logger> logger) {
logger_ = std::move(logger);
OUTCOME_TRY(initGeneralConfig());
OUTCOME_TRY(initOpenMetricsConfig());

return config_;
}

outcome::result<void> Configurator::initGeneralConfig() {
// Init by config-file
if (config_file_.has_value()) {
auto section = (*config_file_)["general"];
if (section.IsDefined()) {
Expand All @@ -214,24 +220,97 @@ namespace jam::app {
file_has_error_ = true;
}
}
auto base_path = section["base_path"];
if (base_path.IsDefined()) {
if (base_path.IsScalar()) {
auto value = base_path.as<std::string>();
config_->base_path_ = value;
} else {
file_errors_ << "E: Value 'general.base_path' must be scalar\n";
file_has_error_ = true;
}
}
auto modules_dir = section["modules_dir"];
if (modules_dir.IsDefined()) {
if (modules_dir.IsScalar()) {
auto value = modules_dir.as<std::string>();
config_->modules_dir_ = value;
} else {
file_errors_ << "E: Value 'general.modules_dir' must be scalar\n";
file_has_error_ = true;
}
}
} else {
file_errors_ << "E: Section 'general' defined, but is not scalar\n";
file_errors_ << "E: Section 'general' defined, but is not map\n";
file_has_error_ = true;
}
}
}

if (file_has_error_) {
std::string path;
find_argument<std::string>(
cli_values_map_, "config", [&](const std::string &value) {
path = value;
});
SL_ERROR(logger_, "Config file `{}` has some problems:", path);
std::istringstream iss(file_errors_.str());
std::string line;
while (std::getline(iss, line)) {
SL_ERROR(logger_, " {}", std::string_view(line).substr(3));
}
return Error::ConfigFileParseFailed;
}

// Adjust by CLI arguments
bool fail;

fail = false;
find_argument<std::string>(
cli_values_map_, "name", [&](const std::string &value) {
config_->name_ = value;
});
find_argument<std::string>(
cli_values_map_, "base_path", [&](const std::string &value) {
config_->base_path_ = value;
});
find_argument<std::string>(
cli_values_map_, "modules_dir", [&](const std::string &value) {
config_->modules_dir_ = value;
});
if (fail) {
return Error::CliArgsParseFailed;
}

// Check values
if (not config_->base_path_.is_absolute()) {
SL_ERROR(logger_,
"The 'base_path' must be defined as absolute: {}",
config_->base_path_.c_str());
return Error::InvalidValue;
}
if (not is_directory(config_->base_path_)) {
SL_ERROR(logger_,
"The 'base_path' does not exist or is not a directory: {}",
config_->base_path_.c_str());
return Error::InvalidValue;
}
current_path(config_->base_path_);

auto make_absolute = [&](const std::filesystem::path &path) {
return weakly_canonical(config_->base_path_.is_absolute()
? path
: (config_->base_path_ / path));
};

config_->modules_dir_ = make_absolute(config_->modules_dir_);
if (not is_directory(config_->modules_dir_)) {
SL_ERROR(logger_,
"The 'modules_dir' does not exist or is not a directory: {}",
config_->modules_dir_.c_str());
return Error::InvalidValue;
}

return outcome::success();
}

Expand Down
6 changes: 5 additions & 1 deletion src/app/configurator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
#pragma once

#include <boost/program_options.hpp>
#include <log/logger.hpp>
#include <qtils/enum_error_code.hpp>
#include <qtils/outcome.hpp>
#include <qtils/strict_sptr.hpp>
#include <yaml-cpp/yaml.h>

#include "injector/dont_inject.hpp"
Expand All @@ -27,6 +29,7 @@ namespace jam::app {
enum class Error : uint8_t {
CliArgsParseFailed,
ConfigFileParseFailed,
InvalidValue,
};

DONT_INJECT(Configurator);
Expand All @@ -49,7 +52,7 @@ namespace jam::app {
outcome::result<YAML::Node> getLoggingConfig();

outcome::result<std::shared_ptr<Configuration>> calculateConfig(
std::shared_ptr<soralog::Logger> logger);
qtils::StrictSharedPtr<soralog::Logger> logger);

private:
outcome::result<void> initGeneralConfig();
Expand All @@ -60,6 +63,7 @@ namespace jam::app {
const char **env_;

std::shared_ptr<Configuration> config_;
std::shared_ptr<soralog::Logger> logger_;

std::optional<YAML::Node> config_file_;
bool file_has_warn_ = false;
Expand Down
28 changes: 13 additions & 15 deletions src/app/impl/application_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
namespace jam::app {

ApplicationImpl::ApplicationImpl(
std::shared_ptr<log::LoggingSystem> logsys,
std::shared_ptr<Configuration> config,
std::shared_ptr<StateManager> state_manager,
std::shared_ptr<Watchdog> watchdog,
std::shared_ptr<metrics::Exposer> metrics_exposer,
std::shared_ptr<clock::SystemClock> system_clock)
qtils::StrictSharedPtr<log::LoggingSystem> logsys,
qtils::StrictSharedPtr<Configuration> config,
qtils::StrictSharedPtr<StateManager> state_manager,
qtils::StrictSharedPtr<Watchdog> watchdog,
qtils::StrictSharedPtr<metrics::Exposer> metrics_exposer,
qtils::StrictSharedPtr<clock::SystemClock> system_clock)
: logger_(logsys->getLogger("Application", "application")),
app_config_(std::move(config)),
state_manager_(std::move(state_manager)),
Expand All @@ -34,15 +34,13 @@ namespace jam::app {
system_clock_(std::move(system_clock)),
metrics_registry_(metrics::createRegistry()) {
// Metric for exposing name and version of node
constexpr auto buildInfoMetricName = "jam_build_info";
metrics_registry_->registerGaugeFamily(
buildInfoMetricName,
"A metric with a constant '1' value labeled by name, version");
auto metric_build_info = metrics_registry_->registerGaugeMetric(
buildInfoMetricName,
{{"name", app_config_->nodeName()},
{"version", app_config_->nodeVersion()}});
metric_build_info->set(1);
metrics::GaugeHelper(
"jam_build_info",
"A metric with a constant '1' value labeled by name, version",
std::map<std::string, std::string>{
{"name", app_config_->nodeName()},
{"version", app_config_->nodeVersion()}})
->set(1);
}

void ApplicationImpl::run() {
Expand Down
Loading
Loading