1 | #pragma once |
2 | |
3 | #include <functional> |
4 | #include <cstring> |
5 | |
6 | // This is necessary for TI_UNREACHABLE |
7 | #include "taichi/common/platform_macros.h" |
8 | |
9 | // Must include "spdlog/common.h" to define SPDLOG_HEADER_ONLY |
10 | // before including "spdlog/fmt/fmt.h" |
11 | #include "spdlog/common.h" |
12 | #include "spdlog/fmt/fmt.h" |
13 | namespace spdlog { |
14 | class logger; |
15 | } |
16 | |
17 | #ifdef _WIN64 |
18 | #define __FILENAME__ \ |
19 | (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) |
20 | #else |
21 | #define __FILENAME__ \ |
22 | (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) |
23 | #endif |
24 | |
25 | #define SPD_AUGMENTED_LOG(X, ...) \ |
26 | taichi::Logger::get_instance().X( \ |
27 | fmt::format("[{}:{}@{}] ", __FILENAME__, __FUNCTION__, __LINE__) + \ |
28 | fmt::format(__VA_ARGS__)) |
29 | |
30 | #if defined(TI_PLATFORM_WINDOWS) |
31 | #define TI_UNREACHABLE __assume(0); |
32 | #else |
33 | #define TI_UNREACHABLE __builtin_unreachable(); |
34 | #endif |
35 | |
36 | #define TI_TRACE(...) SPD_AUGMENTED_LOG(trace, __VA_ARGS__) |
37 | #define TI_DEBUG(...) SPD_AUGMENTED_LOG(debug, __VA_ARGS__) |
38 | #define TI_INFO(...) SPD_AUGMENTED_LOG(info, __VA_ARGS__) |
39 | #define TI_WARN(...) SPD_AUGMENTED_LOG(warn, __VA_ARGS__) |
40 | #define TI_ERROR(...) \ |
41 | { \ |
42 | SPD_AUGMENTED_LOG(error, __VA_ARGS__); \ |
43 | TI_UNREACHABLE; \ |
44 | } |
45 | #define TI_CRITICAL(...) \ |
46 | { \ |
47 | SPD_AUGMENTED_LOG(critical, __VA_ARGS__); \ |
48 | TI_UNREACHABLE; \ |
49 | } |
50 | |
51 | #define TI_TRACE_IF(condition, ...) \ |
52 | if (condition) { \ |
53 | TI_TRACE(__VA_ARGS__); \ |
54 | } |
55 | #define TI_TRACE_UNLESS(condition, ...) \ |
56 | if (!(condition)) { \ |
57 | TI_TRACE(__VA_ARGS__); \ |
58 | } |
59 | #define TI_DEBUG_IF(condition, ...) \ |
60 | if (condition) { \ |
61 | TI_DEBUG(__VA_ARGS__); \ |
62 | } |
63 | #define TI_DEBUG_UNLESS(condition, ...) \ |
64 | if (!(condition)) { \ |
65 | TI_DEBUG(__VA_ARGS__); \ |
66 | } |
67 | #define TI_INFO_IF(condition, ...) \ |
68 | if (condition) { \ |
69 | TI_INFO(__VA_ARGS__); \ |
70 | } |
71 | #define TI_INFO_UNLESS(condition, ...) \ |
72 | if (!(condition)) { \ |
73 | TI_INFO(__VA_ARGS__); \ |
74 | } |
75 | #define TI_WARN_IF(condition, ...) \ |
76 | if (condition) { \ |
77 | TI_WARN(__VA_ARGS__); \ |
78 | } |
79 | #define TI_WARN_UNLESS(condition, ...) \ |
80 | if (!(condition)) { \ |
81 | TI_WARN(__VA_ARGS__); \ |
82 | } |
83 | #define TI_ERROR_IF(condition, ...) \ |
84 | if (condition) { \ |
85 | TI_ERROR(__VA_ARGS__); \ |
86 | } |
87 | #define TI_ERROR_UNLESS(condition, ...) \ |
88 | if (!(condition)) { \ |
89 | TI_ERROR(__VA_ARGS__); \ |
90 | } |
91 | #define TI_CRITICAL_IF(condition, ...) \ |
92 | if (condition) { \ |
93 | TI_CRITICAL(__VA_ARGS__); \ |
94 | } |
95 | #define TI_CRITICAL_UNLESS(condition, ...) \ |
96 | if (!(condition)) { \ |
97 | TI_CRITICAL(__VA_ARGS__); \ |
98 | } |
99 | |
100 | #define TI_ASSERT(x) TI_ASSERT_INFO((x), "Assertion failure: " #x) |
101 | #define TI_ASSERT_INFO(x, ...) \ |
102 | { \ |
103 | bool ___ret___ = static_cast<bool>(x); \ |
104 | if (!___ret___) { \ |
105 | TI_ERROR(__VA_ARGS__); \ |
106 | } \ |
107 | } |
108 | #define TI_NOT_IMPLEMENTED TI_ERROR("Not supported."); |
109 | |
110 | #define TI_STOP TI_ERROR("Stopping here") |
111 | #define TI_TAG TI_INFO("Tagging here") |
112 | |
113 | #define TI_LOG_SET_PATTERN(x) spdlog::set_pattern(x); |
114 | |
115 | #define TI_FLUSH_LOGGER \ |
116 | { taichi::Logger::get_instance().flush(); }; |
117 | |
118 | #define TI_P(x) \ |
119 | { TI_INFO("{}", taichi::TextSerializer::serialize(#x, (x))); } |
120 | |
121 | namespace taichi { |
122 | |
123 | class TI_DLL_EXPORT Logger { |
124 | private: |
125 | std::shared_ptr<spdlog::logger> console_; |
126 | int level_; |
127 | std::function<void()> print_stacktrace_fn_; |
128 | |
129 | Logger(); |
130 | |
131 | public: |
132 | void trace(const std::string &s); |
133 | void debug(const std::string &s); |
134 | void info(const std::string &s); |
135 | void warn(const std::string &s); |
136 | void error(const std::string &s, bool raise_exception = true); |
137 | void critical(const std::string &s); |
138 | void flush(); |
139 | void set_level(const std::string &level); |
140 | bool is_level_effective(const std::string &level_name); |
141 | int get_level(); |
142 | static int level_enum_from_string(const std::string &level); |
143 | void set_level_default(); |
144 | |
145 | // This is mostly to decouple the implementation. |
146 | void set_print_stacktrace_func(std::function<void()> print_fn); |
147 | |
148 | static Logger &get_instance(); |
149 | }; |
150 | |
151 | } // namespace taichi |
152 | |