Skip to content

Commit

Permalink
MON-16329 add grpc log commands (#490)
Browse files Browse the repository at this point in the history
REFS: MON-16329

* MON-16329 add GetLogInfo and SetLogParam grpc commands
  • Loading branch information
jean-christophe81 committed Jan 3, 2023
1 parent a54bdc9 commit e5736e1
Show file tree
Hide file tree
Showing 13 changed files with 435 additions and 44 deletions.
7 changes: 7 additions & 0 deletions broker/core/inc/com/centreon/broker/broker_impl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ class broker_impl final : public Broker::Service {
__attribute__((unused)),
ProcessingStats* response) override;

grpc::Status GetLogInfo(grpc::ServerContext* context [[maybe_unused]],
const GenericString* request,
LogInfo* response) override;
grpc::Status SetLogParam(grpc::ServerContext* context [[maybe_unused]],
const LogParam* request,
::google::protobuf::Empty*) override;

public:
void set_broker_name(const std::string& s);
};
Expand Down
13 changes: 9 additions & 4 deletions broker/core/inc/com/centreon/broker/log_v2.hh
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@

#include "com/centreon/broker/config/state.hh"
#include "com/centreon/broker/namespace.hh"
#include "com/centreon/engine/log_v2_base.hh"

CCB_BEGIN()

class log_v2 : public std::enable_shared_from_this<log_v2> {
std::string _log_name;
class log_v2 : public com::centreon::engine::log_v2_base {
enum logger {
log_bam,
log_bbdo,
Expand All @@ -53,7 +53,6 @@ class log_v2 : public std::enable_shared_from_this<log_v2> {
std::mutex _load_m;

asio::system_timer _flush_timer;
std::chrono::seconds _flush_interval;
std::mutex _flush_timer_m;
bool _flush_timer_active;
std::shared_ptr<asio::io_context> _io_context;
Expand All @@ -70,13 +69,17 @@ class log_v2 : public std::enable_shared_from_this<log_v2> {
public:
~log_v2();

std::shared_ptr<log_v2> shared_from_this() {
return std::static_pointer_cast<log_v2>(
com::centreon::engine::log_v2_base::shared_from_this());
}

void stop_flush_timer();

static void load(const std::shared_ptr<asio::io_context>& io_context);

static log_v2& instance();
void apply(const config::state& conf);
const std::string& log_name() const;

static inline std::shared_ptr<spdlog::logger> bam() {
return get_logger(log_bam, "bam");
Expand Down Expand Up @@ -148,6 +151,8 @@ class log_v2 : public std::enable_shared_from_this<log_v2> {

static bool contains_logger(const std::string& logger);
static bool contains_level(const std::string& level);
std::vector<std::pair<std::string, std::string>> levels() const;
void set_level(const std::string& logger, const std::string& level);
};

CCB_END();
Expand Down
37 changes: 37 additions & 0 deletions broker/core/src/broker.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ service Broker {
*/
rpc RebuildRRDGraphs(IndexIds) returns (google.protobuf.Empty) {}
rpc RemoveGraphs(ToRemove) returns (google.protobuf.Empty) {}
/**
* @brief Retrieve some informations about loggers. If a name is specified,
* Informations are concentrated on the logger of that name.
*
* @param A logger name.
*
* @return A LogInfo message.
*/
rpc GetLogInfo(GenericString) returns (LogInfo) {}

/**
* @brief Set a param of loggers.
*
* @param A message with a logger and a level as strings.
*
* @return nothing.
*/
rpc SetLogParam(LogParam) returns (google.protobuf.Empty) {}
}

message Version {
Expand All @@ -39,6 +57,25 @@ message Version {
int32 patch = 3;
}

message LogInfo {
string log_name = 1;
string log_file = 2;
uint32 log_flush_period = 3;
map<string, string> level = 4;
}


message LogParam {
enum LogParamType {
NONE =0;
FLUSH_PERIOD = 1;
LOG_LEVEL = 2;
}
LogParamType param = 1;
string name = 2;
string value = 3;
}

message GenericString {
string str_arg = 1;
}
Expand Down
64 changes: 64 additions & 0 deletions broker/core/src/broker_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,67 @@ grpc::Status broker_impl::GetProcessingStats(
stats::center::instance().get_processing_stats(response);
return grpc::Status::OK;
}

grpc::Status broker_impl::GetLogInfo(grpc::ServerContext* context
[[maybe_unused]],
const GenericString* request,
LogInfo* response) {
auto& name{request->str_arg()};
auto& map = *response->mutable_level();
auto lvs = log_v2::instance().levels();
response->set_log_name(log_v2::instance().log_name());
response->set_log_file(log_v2::instance().file_path());
response->set_log_flush_period(
log_v2::instance().get_flush_interval().count());
if (!name.empty()) {
auto found = std::find_if(lvs.begin(), lvs.end(),
[&name](std::pair<std::string, std::string>& p) {
return p.first == name;
});
if (found != lvs.end()) {
map[name] = std::move(found->second);
return grpc::Status::OK;
} else {
std::string msg{fmt::format("'{}' is not a logger in broker", name)};
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, msg);
}
} else {
for (auto& p : lvs)
map[p.first] = p.second;
return grpc::Status::OK;
}
}

grpc::Status broker_impl::SetLogParam(grpc::ServerContext* context
[[maybe_unused]],
const LogParam* request,
::google::protobuf::Empty*) {
switch (request->param()) {
case LogParam::LogParamType::LogParam_LogParamType_FLUSH_PERIOD: {
unsigned new_interval;
if (!absl::SimpleAtoi(request->value(), &new_interval)) {
return grpc::Status(
grpc::StatusCode::INVALID_ARGUMENT,
fmt::format("value must be a positive integer instead of {}",
request->value()));
}
log_v2::instance().set_flush_interval(new_interval);
break;
}
case LogParam::LogParamType::LogParam_LogParamType_LOG_LEVEL: {
const std::string& logger_name{request->name()};
const std::string& level{request->value()};
try {
log_v2::instance().set_level(logger_name, level);
} catch (const std::exception& e) {
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what());
}
break;
}
default:
return grpc::Status(
grpc::StatusCode::INVALID_ARGUMENT,
fmt::format("invalid ParamType:{}", request->param()));
}
return grpc::Status::OK;
}
2 changes: 1 addition & 1 deletion broker/core/src/config/applier/init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extern bool g_io_context_started;
void config::applier::init(size_t n_thread, const std::string&) {
// Load singletons.
pool::load(g_io_context, n_thread);
g_io_context_started = n_thread > 0;
g_io_context_started = true;
stats::center::load();
mysql_manager::load();
config::applier::state::load();
Expand Down
82 changes: 63 additions & 19 deletions broker/core/src/log_v2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ log_v2& log_v2::instance() {
}

log_v2::log_v2(const std::shared_ptr<asio::io_context>& io_context)
: _running{false},
: log_v2_base("broker"),
_running{false},
_flush_timer(*io_context),
_flush_timer_active(true),
_io_context(io_context) {
auto stdout_sink = std::make_shared<sinks::stdout_color_sink_mt>();
auto create_logger = [&stdout_sink](const std::string& name) {
std::shared_ptr<spdlog::logger> log =
std::make_shared<spdlog::logger>(name, stdout_sink);
auto create_logger = [&](const std::string& name) {
auto log = std::make_shared<com::centreon::engine::log_v2_logger>(
name, this, stdout_sink);
log->flush_on(level::info);
spdlog::register_logger(log);
return log;
Expand Down Expand Up @@ -86,31 +87,31 @@ void log_v2::apply(const config::state& conf) {

const auto& log = conf.log_conf();

_log_name = log.log_path();
// reset loggers to null sink
auto null_sink = std::make_shared<sinks::null_sink_mt>();
std::shared_ptr<sinks::base_sink<std::mutex>> file_sink;

_file_path = log.log_path();
if (log.max_size)
file_sink = std::make_shared<sinks::rotating_file_sink_mt>(
_log_name, log.max_size, 99);
_file_path, log.max_size, 99);
else
file_sink = std::make_shared<sinks::basic_file_sink_mt>(_log_name);
file_sink = std::make_shared<sinks::basic_file_sink_mt>(_file_path);

auto create_log = [&file_sink, flush_period = log.flush_period](
const std::string& name, level::level_enum lvl) {
auto create_log = [&](const std::string& name, level::level_enum lvl) {
spdlog::drop(name);
auto log = std::make_shared<spdlog::logger>(name, file_sink);
log->set_level(lvl);
auto logger = std::make_shared<com::centreon::engine::log_v2_logger>(
name, this, file_sink);
logger->set_level(lvl);
if (lvl != level::off) {
if (flush_period)
log->flush_on(level::warn);
if (log.flush_period)
logger->flush_on(level::warn);
else
log->flush_on(lvl);
log->set_pattern("[%Y-%m-%dT%H:%M:%S.%e%z] [%n] [%l] %v");
logger->flush_on(lvl);
logger->set_pattern("[%Y-%m-%dT%H:%M:%S.%e%z] [%n] [%l] %v");
}
spdlog::register_logger(log);
return log;
spdlog::register_logger(logger);
return logger;
};

_log[log_v2::log_core] = create_log("core", level::info);
Expand Down Expand Up @@ -195,6 +196,25 @@ bool log_v2::contains_logger(const std::string& logger) {
return std::find(loggers.begin(), loggers.end(), logger) != loggers.end();
}

/**
* @brief Accessor to the various levels of loggers
*
* @return A vector of pairs of strings. The first string is the logger name and
* the second string is its level.
*/
std::vector<std::pair<std::string, std::string>> log_v2::levels() const {
std::vector<std::pair<std::string, std::string>> retval;
if (_running) {
retval.reserve(_log.size());
for (auto& l : _log) {
spdlog::level::level_enum level = l->level();
auto& lv = to_string_view(level);
retval.emplace_back(l->name(), std::string(lv.data(), lv.size()));
}
}
return retval;
}

/**
* @brief this private static method is used to access a specific logger
*
Expand Down Expand Up @@ -228,6 +248,30 @@ bool log_v2::contains_level(const std::string& level) {
return l != level::off;
}

const std::string& log_v2::log_name() const {
return _log_name;
/**
* @brief Set the level of a logger.
*
* @param logger The logger name
* @param level The level as a string
*/
void log_v2::set_level(const std::string& logger, const std::string& level) {
if (_running) {
bool found = false;
for (auto l : _log) {
if (l->name() == logger) {
found = true;
level::level_enum lvl = level::from_str(level);
if (lvl == level::off && level != "off")
throw msg_fmt("The '{}' level is unknown", level);
l->set_level(lvl);
break;
}
}
if (!found)
throw msg_fmt("The '{}' logger does not exist", logger);
} else
throw msg_fmt(
"Unable to change '{}' logger level, the logger is not running for now "
"- try later.",
logger);
}
5 changes: 5 additions & 0 deletions ccc/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ std::string client::call(const std::string& cmd, const std::string& args) {
void* tag;
bool ok = false;
_cq.Next(&tag, &ok);

if (!status_res.ok())
throw com::centreon::exceptions::msg_fmt(
"In call of the '{}' method: {}", cmd_str, status_res.error_message());

grpc::ProtoBufferReader reader(&resp_buf);

const google::protobuf::Descriptor* output_desc = method->output_type();
Expand Down
31 changes: 31 additions & 0 deletions engine/enginerpc/engine.proto
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ service Engine {
rpc EnableNotifications(google.protobuf.Empty) returns (CommandSuccess) {}
rpc DisableServiceNotifications(ServiceIdentifier) returns (CommandSuccess) {}
rpc EnableServiceNotifications(ServiceIdentifier) returns (CommandSuccess) {}

rpc GetLogInfo(google.protobuf.Empty) returns(LogInfo) {}
/**
* @brief Set a param of loggers.
*
* @param A message with a logger and a level as strings.
*
* @return nothing.
*/
rpc SetLogParam(LogParam) returns (google.protobuf.Empty) {}
}

message GenericString {
Expand Down Expand Up @@ -534,3 +544,24 @@ message ChangeObjectCustomVar {
string varname = 4;
string varvalue = 5;
}

message LogInfo {
message LoggerInfo {
string log_name = 1;
string log_file = 2;
uint32 log_flush_period = 3;
map<string, string> level = 4;
}
repeated LoggerInfo loggers = 1;
}

message LogParam {
enum LogParamType {
NONE =0;
FLUSH_PERIOD = 1;
LOG_LEVEL = 2;
}
LogParamType param = 1;
string name = 2;
string value = 3;
}
Loading

0 comments on commit e5736e1

Please sign in to comment.