mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-20 03:35:55 +00:00
* Implement logging abstraction (#371) Fixes #290 * Fix pre-commit to only check staged files * Implement account ownership check and fix paging (#383) Fixes #222 * Remove the github action package signing step This will be done elsewhere. * include searched_all in error response of tx (#407) * helper function for subscribe to ensure cleanup (#402) * Add closed to header for all paths of ledger_data (#416) Fixes #219 * Add custom error for malformed owner and request (#417) Fixes #274 * Use custom malformedAddress error in ledger_entry (#419) Fixes #272 * Return lgrIdxsInvalid error for ledger_max_index less than ledger_min_index (#339) Fixes #263 * Update headers to use #pragma once * Add custom error for malformed request (#414) Fixes #276 * Return srcCurMalformed on invalid taker_pays in book_offers (#413) Fixes #267 * Fix source_location issue on MacOSX and Debug build (#431) Fixes #428 * Implement always adding git ref to version string (#430) Fixes #427 * add connection counting (#433) * Fix malformed output format over ws rpc (#426) Fixes #405 * Remove branch name from version string (#437) Fixes a bug from #430 * Implement cli parsing using boost::po (#436) Fixes #367 * Update documentation and config with ssl_cert_file and ssl_key_file (#443) Fixes #424 * Fix gateway balances to match rippled output (#441) Fixes #271 * Update README and example config to describe start_sequence (#438) Fixes #250 * Add copyright to top of each source file (#444) Fixes #411 * Increase file descriptor limit (#449) * Update readme with more log configurations (#447) Fixes #446 * Document dos_guard in example config. Log when client surpasses rate limit (#451) * Add unit tests for DOSGuard (#453) Fixes #452 * Build macOS and Ubuntu 22.04 (#456) build release/x.y.z branches * Add time measurement profiler (#458) Rebase * Match format to rippled error code (#461) Fixes #263 * Change error message to match rippled (#463) Fixes #263 * Add requests limit to DosGuard (#462) Fixing #448 * Set version to 1.0.4-rc2 Co-authored-by: Alex Kremer <akremer@ripple.com> Co-authored-by: CJ Cobb <46455409+cjcobb23@users.noreply.github.com> Co-authored-by: Francis Mendoza <francissamuelmendoza7@gmail.com> Co-authored-by: cyan317 <120398799+cindyyan317@users.noreply.github.com>
210 lines
6.8 KiB
C++
210 lines
6.8 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of clio: https://github.com/XRPLF/clio
|
|
Copyright (c) 2022, the clio developers.
|
|
|
|
Permission to use, copy, modify, and distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#include <config/Config.h>
|
|
#include <log/Logger.h>
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <filesystem>
|
|
|
|
namespace clio {
|
|
|
|
Logger LogService::general_log_ = Logger{"General"};
|
|
Logger LogService::alert_log_ = Logger{"Alert"};
|
|
|
|
std::ostream&
|
|
operator<<(std::ostream& stream, Severity sev)
|
|
{
|
|
static constexpr std::array<const char*, 6> labels = {
|
|
"TRC",
|
|
"DBG",
|
|
"NFO",
|
|
"WRN",
|
|
"ERR",
|
|
"FTL",
|
|
};
|
|
|
|
return stream << labels.at(static_cast<int>(sev));
|
|
}
|
|
|
|
Severity
|
|
tag_invoke(boost::json::value_to_tag<Severity>, boost::json::value const& value)
|
|
{
|
|
if (not value.is_string())
|
|
throw std::runtime_error("`log_level` must be a string");
|
|
auto const& logLevel = value.as_string();
|
|
|
|
if (boost::iequals(logLevel, "trace"))
|
|
return Severity::TRC;
|
|
else if (boost::iequals(logLevel, "debug"))
|
|
return Severity::DBG;
|
|
else if (boost::iequals(logLevel, "info"))
|
|
return Severity::NFO;
|
|
else if (
|
|
boost::iequals(logLevel, "warning") || boost::iequals(logLevel, "warn"))
|
|
return Severity::WRN;
|
|
else if (boost::iequals(logLevel, "error"))
|
|
return Severity::ERR;
|
|
else if (boost::iequals(logLevel, "fatal"))
|
|
return Severity::FTL;
|
|
else
|
|
throw std::runtime_error(
|
|
"Could not parse `log_level`: expected `trace`, `debug`, `info`, "
|
|
"`warning`, `error` or `fatal`");
|
|
}
|
|
|
|
void
|
|
LogService::init(Config const& config)
|
|
{
|
|
namespace src = boost::log::sources;
|
|
namespace keywords = boost::log::keywords;
|
|
namespace sinks = boost::log::sinks;
|
|
|
|
boost::log::add_common_attributes();
|
|
boost::log::register_simple_formatter_factory<Severity, char>("Severity");
|
|
auto const defaultFormat =
|
|
"%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% "
|
|
"%Message%";
|
|
std::string format =
|
|
config.valueOr<std::string>("log_format", defaultFormat);
|
|
|
|
if (config.valueOr("log_to_console", false))
|
|
{
|
|
boost::log::add_console_log(std::cout, keywords::format = format);
|
|
}
|
|
|
|
auto logDir = config.maybeValue<std::string>("log_directory");
|
|
if (logDir)
|
|
{
|
|
boost::filesystem::path dirPath{logDir.value()};
|
|
if (!boost::filesystem::exists(dirPath))
|
|
boost::filesystem::create_directories(dirPath);
|
|
auto const rotationSize =
|
|
config.valueOr<uint64_t>("log_rotation_size", 2048u) * 1024u *
|
|
1024u;
|
|
auto const rotationPeriod =
|
|
config.valueOr<uint32_t>("log_rotation_hour_interval", 12u);
|
|
auto const dirSize =
|
|
config.valueOr<uint64_t>("log_directory_max_size", 50u * 1024u) *
|
|
1024u * 1024u;
|
|
auto fileSink = boost::log::add_file_log(
|
|
keywords::file_name = dirPath / "clio.log",
|
|
keywords::target_file_name = dirPath / "clio_%Y-%m-%d_%H-%M-%S.log",
|
|
keywords::auto_flush = true,
|
|
keywords::format = format,
|
|
keywords::open_mode = std::ios_base::app,
|
|
keywords::rotation_size = rotationSize,
|
|
keywords::time_based_rotation =
|
|
sinks::file::rotation_at_time_interval(
|
|
boost::posix_time::hours(rotationPeriod)));
|
|
fileSink->locked_backend()->set_file_collector(
|
|
sinks::file::make_collector(
|
|
keywords::target = dirPath, keywords::max_size = dirSize));
|
|
fileSink->locked_backend()->scan_for_files();
|
|
}
|
|
|
|
// get default severity, can be overridden per channel using
|
|
// the `log_channels` array
|
|
auto defaultSeverity = config.valueOr<Severity>("log_level", Severity::NFO);
|
|
static constexpr std::array<const char*, 7> channels = {
|
|
"General",
|
|
"WebServer",
|
|
"Backend",
|
|
"RPC",
|
|
"ETL",
|
|
"Subscriptions",
|
|
"Performance",
|
|
};
|
|
|
|
auto core = boost::log::core::get();
|
|
auto min_severity = boost::log::expressions::channel_severity_filter(
|
|
log_channel, log_severity);
|
|
|
|
for (auto const& channel : channels)
|
|
min_severity[channel] = defaultSeverity;
|
|
min_severity["Alert"] =
|
|
Severity::WRN; // Channel for alerts, always warning severity
|
|
|
|
for (auto const overrides = config.arrayOr("log_channels", {});
|
|
auto const& cfg : overrides)
|
|
{
|
|
auto name = cfg.valueOrThrow<std::string>(
|
|
"channel", "Channel name is required");
|
|
if (not std::count(std::begin(channels), std::end(channels), name))
|
|
throw std::runtime_error(
|
|
"Can't override settings for log channel " + name +
|
|
": invalid channel");
|
|
|
|
min_severity[name] =
|
|
cfg.valueOr<Severity>("log_level", defaultSeverity);
|
|
}
|
|
|
|
core->set_filter(min_severity);
|
|
LogService::info() << "Default log level = " << defaultSeverity;
|
|
}
|
|
|
|
Logger::Pump
|
|
Logger::trace(source_location_t const& loc) const
|
|
{
|
|
return {logger_, Severity::TRC, loc};
|
|
};
|
|
Logger::Pump
|
|
Logger::debug(source_location_t const& loc) const
|
|
{
|
|
return {logger_, Severity::DBG, loc};
|
|
};
|
|
Logger::Pump
|
|
Logger::info(source_location_t const& loc) const
|
|
{
|
|
return {logger_, Severity::NFO, loc};
|
|
};
|
|
Logger::Pump
|
|
Logger::warn(source_location_t const& loc) const
|
|
{
|
|
return {logger_, Severity::WRN, loc};
|
|
};
|
|
Logger::Pump
|
|
Logger::error(source_location_t const& loc) const
|
|
{
|
|
return {logger_, Severity::ERR, loc};
|
|
};
|
|
Logger::Pump
|
|
Logger::fatal(source_location_t const& loc) const
|
|
{
|
|
return {logger_, Severity::FTL, loc};
|
|
};
|
|
|
|
std::string
|
|
Logger::Pump::pretty_path(source_location_t const& loc, size_t max_depth) const
|
|
{
|
|
auto const file_path = std::string{loc.file_name()};
|
|
auto idx = file_path.size();
|
|
while (max_depth-- > 0)
|
|
{
|
|
idx = file_path.rfind('/', idx - 1);
|
|
if (idx == std::string::npos || idx == 0)
|
|
break;
|
|
}
|
|
return file_path.substr(idx == std::string::npos ? 0 : idx + 1) + ':' +
|
|
std::to_string(loc.line());
|
|
}
|
|
|
|
} // namespace clio
|