1 #include <boost/algorithm/string/classification.hpp>
2 #include <boost/algorithm/string/join.hpp>
3 #include <boost/algorithm/string/predicate.hpp>
4 #include <boost/algorithm/string/split.hpp>
5 #include <boost/program_options.hpp>
6 #include <boost/filesystem.hpp>
11 #include <fc/log/console_appender.hpp>
12 #include <fc/log/file_appender.hpp>
13 #include <fc/log/gelf_appender.hpp>
14 #include <fc/log/logger.hpp>
15 #include <fc/log/logger_config.hpp>
16 #include <fc/io/json.hpp>
17 #include <fc/network/ip.hpp>
18 #include <fc/exception/exception.hpp>
24 #define LOG_APPENDER "log-appender"
25 #define LOGGER "log-logger"
26 #define DEFAULT_GELF_APPENDER_PORT 12201
28 namespace bpo = boost::program_options;
64 fc::appender_config get_console_config(
const std::string& s)
68 auto stream = fc::variant(appender.stream).as<fc::console_appender::stream::type>();
70 fc::console_appender::config config;
71 config.level_colors.emplace_back(
72 fc::console_appender::level_color(fc::log_level::debug, fc::console_appender::color::white));
73 config.level_colors.emplace_back(
74 fc::console_appender::level_color(fc::log_level::info, fc::console_appender::color::green));
75 config.level_colors.emplace_back(
76 fc::console_appender::level_color(fc::log_level::warn, fc::console_appender::color::brown));
77 config.level_colors.emplace_back(
78 fc::console_appender::level_color(fc::log_level::error, fc::console_appender::color::red));
81 return fc::appender_config::create_config<fc::console_appender>(appender.appender, fc::variant(config));
84 fc::appender_config get_file_config(
const std::string& s,
const boost::filesystem::path& pwd)
88 fc::path file_name = file_appender.
stream;
90 if (file_name.is_relative())
92 file_name = fc::absolute(pwd) / file_name;
95 ilog(file_name.generic_string());
97 if (fc::is_directory(file_name))
99 FC_THROW_EXCEPTION(fc::invalid_arg_exception,
"appender stream ${name} is not a file", (
"name", file_name));
104 fc::file_appender::config config;
105 config.filename = file_name;
107 config.rotate =
true;
108 config.rotation_interval = fc::minutes(file_appender.rotation_interval_minutes);
109 config.rotation_limit = fc::hours(file_appender.rotation_limit_hours);
111 return fc::appender_config::create_config<fc::file_appender>(file_appender.appender, fc::variant(config));
114 fc::appender_config get_gelf_config(
const std::string& s,
const std::string& optional_info =
"")
119 std::string endpoint = gelf_appender.
stream;
120 if (endpoint.find(
':') == std::string::npos)
125 fc::ip::endpoint::from_string(endpoint);
127 fc::gelf_appender::config config;
128 config.endpoint = endpoint;
129 config.host_name = gelf_appender.host_name;
131 config.additional_info = optional_info;
133 if (!gelf_appender.additional_info.empty())
135 if (!config.additional_info.empty())
136 config.additional_info +=
": ";
137 config.additional_info += gelf_appender.additional_info;
140 return fc::appender_config::create_config<fc::gelf_appender>(gelf_appender.appender, fc::variant(config));
144 const boost::filesystem::path& pwd)
149 fc::logging_config logging_config;
150 bool found_logging_config =
false;
154 std::vector<std::string> appenders = args[
LOG_APPENDER].as<std::vector<std::string>>();
156 for (
const std::string& s : appenders)
161 logging_config.appenders.push_back(get_console_config(s));
163 found_logging_config =
true;
166 catch (fc::bad_cast_exception&)
175 if (args.count(
"witness"))
179 const std::vector<std::string>& witnesses = args[
"witness"].as<std::vector<std::string>>();
180 if (!witnesses.empty())
182 witness =
"witness " + boost::algorithm::join(witnesses,
" ");
185 FC_CAPTURE_AND_LOG(())
188 logging_config.appenders.push_back(get_gelf_config(s, witness));
190 found_logging_config =
true;
193 catch (fc::exception& e)
200 logging_config.appenders.push_back(get_file_config(s, pwd));
202 found_logging_config =
true;
205 catch (fc::exception&)
213 std::vector<std::string> loggers = args[
LOGGER].as<std::vector<std::string>>();
215 for (std::string& s : loggers)
219 fc::logger_config logger_config(
logger.name);
220 logger_config.level = fc::variant(
logger.level).as<fc::log_level>();
221 boost::split(logger_config.appenders,
logger.appender, boost::is_any_of(
" ,"), boost::token_compress_on);
222 logging_config.loggers.push_back(logger_config);
224 found_logging_config =
true;
228 if (found_logging_config)
229 return logging_config;
231 return fc::optional<fc::logging_config>();
233 FC_RETHROW_EXCEPTIONS(warn,
"")
240 std::vector<std::string> default_appender({
241 R
"({"appender":"stderr","stream":"std_error"})",
242 LOG_APPENDER R"( = {"appender":"p2p","stream":"logs/p2p.log","rotation_interval_minutes":"120", "rotation_limit_hours":"720"})",
243 LOG_APPENDER R"( = {"appender":"node","stream":"logs/node.log","rotation_interval_minutes":"120", "rotation_limit_hours":"720"})",
244 "# " LOG_APPENDER R
"( = {"appender":"remote","stream":"127.0.0.1:12201", "host_name":"", "additional_info":""})"
246 std::string str_default_appender = boost::algorithm::join(default_appender, "\n");
249 std::vector< std::string > default_logger(
250 { R
"({"name":"default","level":"info","appender":"stderr, node"})",
251 LOGGER R"( = {"name":"p2p","level":"info","appender":"p2p"})" });
252 std::string str_default_logger = boost::algorithm::join(default_logger, "\n");
255 std::vector< std::string > default_appender_description(
256 { R
"(Console appender definition json: {"appender", "stream"})" ,
257 R"(File appender definition json: {"appender", "stream", "rotation_interval_minutes", "rotation_limit_hours"})",
258 R"(Gelf appender definition json: {"appender", "stream", "host_name", "additional_info"})" });
259 std::string str_default_appender_description = boost::algorithm::join(default_appender_description, "\n# ");
261 auto default_value = [](
const std::vector<std::string>& args,
const std::string& str)
263 return boost::program_options::value<std::vector<std::string>>()->composing()->default_value(args, str);
266 options.add_options()
267 (
LOG_APPENDER, default_value(default_appender, str_default_appender), str_default_appender_description.c_str())
268 (
LOGGER, default_value(default_logger, str_default_logger), R
"(Logger definition json: {"name", "level", "appender"})" );
#define SCORUM_BLOCKCHAIN_VERSION
FC_REFLECT(appender_args,(appender)(stream)) FC_REFLECT_DERIVED(file_appender_args
()() host_name(additional_info)) FC_REFLECT(logger_args
() rotation_interval_minutes(rotation_limit_hours)) FC_REFLECT_DERIVED(gelf_appender_args
#define DEFAULT_GELF_APPENDER_PORT
()()() name() level(appender)) namespace logger
fc::optional< fc::logging_config > load_logging_config_from_options(const boost::program_options::variables_map &args, const boost::filesystem::path &pwd)
void set_logging_program_options(boost::program_options::options_description &options)
size_t rotation_interval_minutes
size_t rotation_limit_hours
std::string additional_info