knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
Logger.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of KnowRob, please consult
3  * https://github.com/knowrob/knowrob for license details.
4  */
5 
6 #include <knowrob/Logger.h>
7 #include <spdlog/sinks/stdout_color_sinks.h>
8 #include <spdlog/sinks/rotating_file_sink.h>
9 #include "knowrob/integration/python/utils.h"
10 #include "knowrob/URI.h"
11 
12 using namespace knowrob;
13 
14 struct Logger::impl {
15  std::shared_ptr<spdlog::sinks::stdout_color_sink_mt> console_sink;
16  std::shared_ptr<spdlog::sinks::rotating_file_sink_mt> file_sink;
17  std::shared_ptr<spdlog::logger> logger;
18 
19  impl()
20  : console_sink(std::make_shared<spdlog::sinks::stdout_color_sink_mt>()) {}
21 };
22 
24  : pimpl_{std::make_unique<impl>()} {
25  updateLogger();
26 }
27 
29  if (pimpl_->file_sink)
30  pimpl_->logger = std::make_shared<spdlog::logger>(
31  "multi_sink", spdlog::sinks_init_list({pimpl_->console_sink, pimpl_->file_sink}));
32  else
33  pimpl_->logger = std::make_shared<spdlog::logger>(
34  "multi_sink", spdlog::sinks_init_list({pimpl_->console_sink}));
35  spdlog::set_default_logger(pimpl_->logger);
36  spdlog::set_level(spdlog::level::trace);
37  spdlog::flush_every(std::chrono::seconds(2));
38 }
39 
41  static Logger singleton;
42  return singleton;
43 }
44 
46  setSinkLevel(Console, spdlog::level::info);
47  setSinkPattern(Console, "[%$%H:%M:%S.%e] [%^%l%$] %v");
48 }
49 
50 static std::filesystem::path getLoggingPath(const boost::optional<std::string> &logDir) {
51  if (logDir.has_value()) {
52  return logDir.value();
53  } else {
54  std::vector<std::filesystem::path> consideredPaths;
55 
56  auto homePath = URI::getHomePath();
57  if (homePath.has_value()) {
58  consideredPaths.push_back(std::filesystem::path(homePath.value()) / ".knowrob" / "logs");
59  }
60  consideredPaths.push_back(std::filesystem::temp_directory_path() / "knowrob" / "logs");
61  consideredPaths.push_back(std::filesystem::current_path());
62 
63  for (const auto &path : consideredPaths) {
64  if (!std::filesystem::exists(path)) {
65  if (!std::filesystem::create_directories(path)) {
66  continue;
67  }
68  }
69  if (!std::filesystem::is_directory(path)) continue;
70  return path;
71  }
72  return std::filesystem::current_path();
73  }
74 }
75 
76 void Logger::loadConfiguration(boost::property_tree::ptree &config) {
77  auto consoleConfig = config.get_child_optional("console-sink");
78  if (consoleConfig) {
79  auto level = consoleConfig.value().get_optional<std::string>("level");
80  auto pattern = consoleConfig.value().get_optional<std::string>("pattern");
81  if (level.has_value()) {
82  setSinkLevel(Console, spdlog::level::from_str(level.value()));
83  }
84  if (pattern.has_value()) {
85  setSinkPattern(Console, pattern.value());
86  }
87  }
88 
89  auto fileConfig = config.get_child_optional("file-sink");
90  if (fileConfig) {
91  auto &fileConfig0 = fileConfig.value();
92  auto path = getLoggingPath(fileConfig0.get_optional<std::string>("path"));
93  auto basename = fileConfig0.get<std::string>("basename", "knowrob.log");
94 
95  KB_INFO("[KnowRob] Writing logs to {}", path.native());
96 
97  setupFileSink((path / basename).native(),
98  fileConfig0.get<bool>("rotate", true),
99  fileConfig0.get<uint32_t>("max_size", 1048576),
100  fileConfig0.get<uint32_t>("max_files", 4));
101 
102  auto level = fileConfig0.get_optional<std::string>("level");
103  auto pattern = fileConfig0.get_optional<std::string>("pattern");
104  if (level.has_value()) {
105  setSinkLevel(File, spdlog::level::from_str(level.value()));
106  }
107  if (pattern.has_value()) {
108  setSinkPattern(File, pattern.value());
109  }
110  }
111 
112  auto flushInterval = config.get_optional<int64_t>("flush-interval");
113  if (flushInterval.has_value()) {
114  spdlog::flush_every(std::chrono::seconds(flushInterval.value()));
115  }
116 }
117 
118 void Logger::setupFileSink(const std::string &basename,
119  bool rotate,
120  uint32_t max_size,
121  uint32_t max_files) {
122  auto &self = get();
123  self.pimpl_->file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
124  basename, max_size, max_files, rotate);
125  setSinkLevel(File, spdlog::level::trace);
126  setSinkPattern(File, "[%c] [thread:%t] [%^%l%$] %v (%s:%#)");
127  self.updateLogger();
128 }
129 
130 void Logger::setSinkLevel(SinkType sinkType, spdlog::level::level_enum log_level) {
131  switch (sinkType) {
132  case Console:
133  get().pimpl_->console_sink->set_level(log_level);
134  break;
135  case File:
136  if (get().pimpl_->file_sink)
137  get().pimpl_->file_sink->set_level(log_level);
138  break;
139  }
140 }
141 
143  switch (sinkType) {
144  case Console:
145  get().pimpl_->console_sink->set_pattern(pattern);
146  break;
147  case File:
148  if (get().pimpl_->file_sink)
149  get().pimpl_->file_sink->set_pattern(pattern);
150  break;
151  }
152 }
153 
155  if (name.empty()) {
156  return fmt::format(R"(Failed to execute action of type "{}")", type);
157  } else {
158  return fmt::format(R"(Component "{}" failed to execute action of type "{}")", name, type);
159  }
160 }
161 
162 namespace knowrob::py {
163  template<>
165  using namespace boost::python;
166  def("logInfo", +[](const std::string &msg) { KB_INFO(msg); });
167  def("logWarn", +[](const std::string &msg) { KB_WARN(msg); });
168  def("logError", +[](const std::string &msg) { KB_ERROR(msg); });
169  def("logDebug", +[](const std::string &msg) { KB_DEBUG(msg); });
170  def("logCritical", +[](const std::string &msg) { KB_CRITICAL(msg); });
171  }
172 }
#define KB_DEBUG
Definition: Logger.h:25
#define KB_INFO
Definition: Logger.h:26
#define KB_CRITICAL
Definition: Logger.h:29
#define KB_ERROR
Definition: Logger.h:28
#define KB_WARN
Definition: Logger.h:27
static void setupFileSink(const std::string &basename="knowrob.log", bool rotate=true, uint32_t max_size=1048576, uint32_t max_files=4)
Definition: Logger.cpp:118
static void setSinkLevel(SinkType sinkType, spdlog::level::level_enum log_level)
Definition: Logger.cpp:130
static std::string formatGenericFailure(const std::string &name, const std::string &type)
Definition: Logger.cpp:154
static void loadConfiguration(boost::property_tree::ptree &config)
Definition: Logger.cpp:76
static void setSinkPattern(SinkType sinkType, const std::string &pattern)
Definition: Logger.cpp:142
void updateLogger()
Definition: Logger.cpp:28
static Logger & get()
Definition: Logger.cpp:40
std::unique_ptr< impl > pimpl_
Definition: Logger.h:128
static void initialize()
Definition: Logger.cpp:45
static std::optional< std::string > getHomePath(void)
Definition: URI.cpp:53
GraphTermRule & pattern()
Definition: graph.cpp:23
TermRule & string()
Definition: terms.cpp:63
void createType< Logger >()
Definition: Logger.cpp:164
const IRIAtomPtr type
Definition: rdf.h:15