Go to the documentation of this file.
20 #include <farm_pp/preprocessor/comma.hpp>
21 #include <farm_pp/preprocessor/empty.hpp>
25 #include <unordered_set>
54 std::function<std::string()>
now;
60 template <
typename... TT>
63 std::string
const& header_text,
64 std::string
const& file,
66 std::string
const&
function,
69 if (log_level_ <= LogLevel::warning &&
70 (log_level == LogLevel::debug || log_level == LogLevel::trace)) {
73 if (noisy_modules_.find(file) == noisy_modules_.end()) {
75 noisy_modules_.insert(file);
77 writeHeader(LogLevel::warning, header_text, file, line,
function);
79 "Noisy logging (DEBUG or TRACE) enabled for module: {} (runtime "
88 if (log_level_ <= log_level) {
89 writeHeader(log_level, header_text, file, line,
function);
97 std::string
const& header_text,
98 std::string
const& file,
100 std::string
const&
function) {
101 this->
log(log_level, header_text, file, line,
function, std::string(
""));
107 std::string
const& header_text,
108 std::string
const& file,
110 std::string
const&
function);
111 static void write(std::string
const&
str);
114 static std::string
const kDefaultHeaderFormat;
115 static LogLevel
const kDefaultLogLevel = LogLevel(LogLevel::info);
116 static LogClock
const kDefaultLogClock;
118 std::string header_format_ = kDefaultHeaderFormat;
119 LogLevel log_level_ = kDefaultLogLevel;
120 LogClock log_clock_ = kDefaultLogClock;
121 std::unordered_set<std::string> noisy_modules_;
126 return Static_Logger;
132 #define FARM_VARGS(...) FARM_PP_COMMA() __VA_ARGS__
134 #define FARM_VARGS_NONE(...)
136 #define FARM_MAYBE_VARGS(...) \
138 FARM_PP_EQUAL(FARM_PP_VARIADIC_SIZE(dummy, ##__VA_ARGS__), 1), \
143 #define FARM_LOG_ENABLED 1
145 #ifdef FARM_LOG_ENABLED
151 #define FARM_INFO(...) \
152 farm_ng::defaultLogger().log( \
153 farm_ng::LogLevel::info, \
161 #define FARM_WARN(...) \
162 farm_ng::defaultLogger().log( \
163 farm_ng::LogLevel::warning, \
171 #define FARM_ERROR(...) \
172 farm_ng::defaultLogger().log( \
173 farm_ng::LogLevel::error, \
181 #define FARM_CRITICAL(...) \
182 farm_ng::defaultLogger().log( \
183 farm_ng::LogLevel::critical, \
190 #define FARM_INFO(...)
191 #define FARM_WARN(...)
192 #define FARM_ERROR(...)
193 #define FARM_CRITICAL(...)
196 #define FARM_IMPL_ASSERT_OP(symbol, name_str, lhs, rhs, ...) \
198 if (!((lhs)symbol(rhs))) { \
199 farm_ng::defaultLogger().log( \
200 farm_ng::LogLevel::critical, \
202 "PANIC: ASSERT_{} failed\n Not true: {} {} {}\n{}\nvs.\n{}\n", \
211 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
217 #define FARM_IMPL_LOG_HEADER(msg) \
218 FARM_IMPL_LOG_PRINTLN("[FARM {} in {}:{}]", msg, __FILE__, __LINE__)
223 #define FARM_PANIC(...) \
224 farm_ng::defaultLogger().log( \
225 farm_ng::LogLevel::critical, \
229 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
233 #define FARM_UNIMPLEMENTED(...) \
234 farm_ng::defaultLogger().log( \
235 farm_ng::LogLevel::critical, \
236 "PANIC: NOT IMPLEMENTED YET", \
239 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
243 #define FARM_PRINTLN(cstr, ...) FARM_IMPL_LOG_PRINTLN(cstr, ##__VA_ARGS__)
246 #define FARM_INFO_EVERY_N(N, ...) \
248 static std::atomic<int> counter(0); \
250 if (counter > (N)) { \
253 if (counter == 1) { \
254 farm_ng::defaultLogger().log( \
255 farm_ng::LogLevel::info, \
256 FARM_FORMAT("LOG INFO EVERY N( = {} )", #N), \
259 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
264 #define FARM_ASSERT(condition, ...) \
266 if (!(condition)) { \
267 farm_ng::defaultLogger().log( \
268 farm_ng::LogLevel::critical, \
269 FARM_FORMAT("PANIC: ASSERT failed\nbool({}) not true.", #condition), \
272 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
279 #define FARM_ASSERT_EQ(lhs, rhs, ...) \
280 FARM_IMPL_ASSERT_OP(==, "EQ", lhs, rhs, __VA_ARGS__)
284 #define FARM_ASSERT_NE(lhs, rhs, ...) \
285 FARM_IMPL_ASSERT_OP(!=, "NE", lhs, rhs, __VA_ARGS__)
289 #define FARM_ASSERT_LE(lhs, rhs, ...) \
290 FARM_IMPL_ASSERT_OP(<=, "LE", lhs, rhs, __VA_ARGS__)
294 #define FARM_ASSERT_LT(lhs, rhs, ...) \
295 FARM_IMPL_ASSERT_OP(<, "LT", lhs, rhs, __VA_ARGS__)
299 #define FARM_ASSERT_GE(lhs, rhs, ...) \
300 FARM_IMPL_ASSERT_OP(>=, "GE", lhs, rhs, __VA_ARGS__)
304 #define FARM_ASSERT_GT(lhs, rhs, ...) \
305 FARM_IMPL_ASSERT_OP(>, "GT", lhs, rhs, __VA_ARGS__)
310 template <
class TPo
int,
class TEnabler =
void>
314 struct CheckNear<TT, std::enable_if_t<std::is_arithmetic_v<TT>, void>> {
319 char const* lhs_cstr,
320 char const* rhs_cstr,
321 char const* thr_cstr,
322 std::string
const& file,
324 std::string
const&
func,
325 std::string
const&
str) {
328 auto lhs_abs = abs(lhs);
329 auto rhs_abs = abs(rhs);
330 if (
min(lhs_abs, rhs_abs) < thr) {
332 auto err = abs(lhs - rhs);
333 if (!(err < (thr))) {
335 farm_ng::LogLevel::critical,
337 "ASSERT_NEAR absolute]\n"
338 "Not true: {} (={}) near {} (={}); has error of {} (thr: "
355 double err = abs(lhs / rhs - 1.0);
356 if (!(err < (thr))) {
358 farm_ng::LogLevel::critical,
360 "ASSERT_NEAR relative]\n"
361 "Not true: {} (={}) near {} (={}); has error of {} (thr: "
387 #define FARM_ASSERT_NEAR(lhs, rhs, thr, ...) \
388 ::farm_ng::details::CheckNear<std::decay_t<decltype(lhs)>>::impl( \
398 FARM_FORMAT(__VA_ARGS__))
409 template <
class TContainer>
411 TContainer& container,
413 char const* container_cstr,
414 char const* index_cstr,
415 std::string
const& file,
417 std::string
const&
func,
418 std::string
const&
str) -> decltype(container[index]) {
419 if (index >= container.size()) {
421 farm_ng::LogLevel::critical,
423 "FARM_AT index `{}` (={}) not in contiguous container `{}` of size "
435 return container[index];
438 template <
class TContainer,
class TKey>
440 TContainer& container,
442 char const* container_cstr,
443 char const* key_cstr,
444 std::string
const& file,
446 std::string
const&
func,
447 std::string
const&
str) -> decltype(*(container.find(key))) {
448 auto it = container.find(key);
449 if (it == container.end()) {
451 farm_ng::LogLevel::critical,
453 "FARM_GET key `{}` (={}) not in associative container `{}` of size "
468 template <
class TMapLike,
class TKey,
class TValue>
473 char const* container_cstr,
474 char const* key_cstr,
475 char const* value_cstr,
476 std::string
const& file,
478 std::string
const&
func,
479 std::string
const&
str) {
480 auto const [iterator, success] = map.insert({key, value});
484 farm_ng::LogLevel::critical,
486 "FARM_INSERT key `{}` (={}) is already in map `{}` of size `{}`.\n"
487 "We cannot insert value `{}`.",
502 template <
class TWrapper>
506 char const* wrapper_cstr,
508 if (!
bool(wrapper)) {
510 farm_ng::LogLevel::critical,
512 "FARM_UNWRAP wrapper type `{}` does not contain a valid value",
524 template <
class TWrapper>
527 -> decltype(*wrapper) {
536 #define FARM_AT(contiguous_container, index, ...) \
537 farm_ng::details::checkedAtContiguousContainer( \
538 contiguous_container, \
540 #contiguous_container, \
545 FARM_FORMAT(__VA_ARGS__))
549 #define FARM_GET(associative_container, key, ...) \
550 farm_ng::details::checkedGetFromAssociativeContainer( \
551 associative_container, \
553 #associative_container, \
558 FARM_FORMAT(__VA_ARGS__))
562 #define FARM_MAP_INSERT(map, key, value, ...) \
563 farm_ng::details::insertKeyValueInMap( \
573 FARM_FORMAT(__VA_ARGS__))
576 #define FARM_UNWRAP(wrapper, ...) \
577 farm_ng::details::unwrapImpl( \
580 ::farm_ng::ErrorDetail{ \
583 .msg = FARM_FORMAT(__VA_ARGS__)})
586 #define FARM_ASSERT_PATH_EXIST(path, ...) \
588 bool does_exist = std::filesystem::exists(path); \
590 farm_ng::defaultLogger().log( \
591 farm_ng::LogLevel::critical, \
593 "PANIC: ASSERT_PATH_EXIST failed\nThe following path does not " \
598 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
607 #define FARM_ASSERT_IS_FILE(path, ...) \
609 FARM_ASSERT_PATH_EXIST(path); \
610 bool is_regular = std::filesystem::is_regular_file(path); \
612 farm_ng::defaultLogger().log( \
613 farm_ng::LogLevel::critical, \
615 "PANIC: ASSERT_IS_FILE failed\nThe following path is not a " \
616 "regular file: {}", \
620 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
629 #define FARM_ASSERT_IS_FOLDER(path, ...) \
631 FARM_ASSERT_PATH_EXIST(path); \
632 bool is_folder = std::filesystem::is_directory(path); \
634 farm_ng::defaultLogger().log( \
635 farm_ng::LogLevel::critical, \
637 "PANIC: ASSERT_IS_FOLDER failed\nThe following path is not a " \
642 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
652 #define FARM_ASSERT_FOLDER_IS_EMPTY(path, ...) \
654 FARM_ASSERT_IS_FOLDER(path); \
655 bool is_empty = std::filesystem::is_empty(path); \
657 farm_ng::defaultLogger().log( \
658 farm_ng::LogLevel::critical, \
660 "PANIC: ASSERT_FOLDER_IS_EMPTY failed\nThe following folder is " \
665 __func__ FARM_MAYBE_VARGS(__VA_ARGS__)(__VA_ARGS__)); \
Definition: backtrace.cpp:102
std::function< std::string()> now
Definition: logger.h:54
str
Definition: event_service.py:547
FARM_ENUM(LogLevel, int,((trace, 0),(debug, 1),(info, 2),(warning, 3),(error, 4),(critical, 5)))
auto min(TPoint const &a, TPoint const &b) -> TPoint
Definition: vector_space.h:104
args
Definition: event_service.py:549
void log(LogLevel log_level, std::string const &header_text, std::string const &file, int line, std::string const &function, std::string const &message, TT &&... args)
Definition: logger.h:61
void setLogClock(LogClock log_clock)
Definition: logger.cpp:37
LogLevel getLogLevel()
Definition: logger.cpp:35
int line
Definition: logger.h:403
void log(LogLevel log_level, std::string const &header_text, std::string const &file, int line, std::string const &function)
Definition: logger.h:95
cmake message("farm_ng_cmake_DIR" ${farm_ng_cmake_DIR}) include($
Definition: CMakeLists.txt:8
std::string getHeaderFormat() const
Definition: logger.cpp:30
auto stringFromLogLevel(LogLevel level) -> std::string
Definition: logger.cpp:21
auto checkedGetFromAssociativeContainer(TContainer &container, TKey const &key, char const *container_cstr, char const *key_cstr, std::string const &file, int line, std::string const &func, std::string const &str) -> decltype(*(container.find(key)))
Definition: logger.h:439
std::string file
Definition: logger.h:402
level
Definition: event_client.py:41
StreamLogger & defaultLogger()
Definition: logger.h:124
auto insertKeyValueInMap(TMapLike &map, TKey const &key, TValue const &value, char const *container_cstr, char const *key_cstr, char const *value_cstr, std::string const &file, int line, std::string const &func, std::string const &str)
Definition: logger.h:469
void setHeaderFormat(std::string const &str)
Definition: logger.cpp:27
static auto impl(TWrapper &wrapper, char const *wrapper_cstr, ::farm_ng::ErrorDetail detail) -> decltype(*wrapper)
Definition: logger.h:504
void setLogLevel(LogLevel level)
Definition: logger.cpp:34
static void impl(double const &lhs, double const &rhs, double const &thr, char const *lhs_cstr, char const *rhs_cstr, char const *thr_cstr, std::string const &file, int line, std::string const &func, std::string const &str)
Definition: logger.h:315
auto unwrapImpl(TWrapper &wrapper, char const *wrapper_cstr, ::farm_ng::ErrorDetail detail) -> decltype(*wrapper)
Definition: logger.h:525
std::string msg
Definition: logger.h:404
func
Definition: event_service_recorder.py:420
auto checkedAtContiguousContainer(TContainer &container, size_t index, char const *container_cstr, char const *index_cstr, std::string const &file, int line, std::string const &func, std::string const &str) -> decltype(container[index])
Definition: logger.h:410