GCC Code Coverage Report


Directory: ./
File: src/logging/_logging.h
Date: 2023-04-27 00:55:30
Exec Total Coverage
Lines: 22 26 84.6%
Functions: 19 26 73.1%
Branches: 20 38 52.6%

Line Branch Exec Source
1 #ifndef LYTHON_LOGGING_H
2 #define LYTHON_LOGGING_H
3
4 #include <cassert>
5 #include <string>
6 #include <vector>
7
8 #include "revision_data.h"
9
10 #include <spdlog/fmt/bundled/core.h>
11
12 // This file should not include spdlog
13 // spdlog file is compile time cancer so it is only included inside the .cpp
14
15 namespace lython {
16
17 // Path to repository on current system
18 constexpr char __source_dir[] = _SOURCE_DIRECTORY;
19 // Length of the path so we can cut unimportant folders
20 constexpr int __size_src_dir = sizeof(_SOURCE_DIRECTORY) / sizeof(char);
21
22 struct CodeLocation {
23 CodeLocation(std::string const& file,
24 std::string const& fun,
25 int line,
26 107 std::string const& fun_long):
27 107 filename(file.substr(__size_src_dir)),
28
2/4
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
107 function_name(fun), line(line), function_long(fun_long) {}
29
30 std::string filename;
31 std::string function_name;
32 int line;
33 std::string function_long;
34
35 static CodeLocation const& noloc() {
36 static CodeLocation loc(__FILE__, "", 0, "");
37 return loc;
38 }
39
40 std::string repr() const { return fmt::format("{}:{} {}", filename, line, function_name); }
41 };
42
43 // Avoid spending time creating the same codeloc multiple time
44 // clang-format off
45 using CodeLocationConstRef = CodeLocation const&;
46
47 #define MAKE_LOC(fun, funp) lython::CodeLocation(__FILE__, fun, __LINE__, funp)
48 #define LAMBDA_LOC(fun, funp) (([](const char* afun, const char* afunp) -> lython::CodeLocationConstRef { static lython::CodeLocation loc = lython::CodeLocation(__FILE__, afun, __LINE__, afunp); return loc; })(fun, funp))
49 // clang-format on
50
51 #if WITH_LOG
52 # ifdef __linux__
53 # define LOC LAMBDA_LOC(__FUNCTION__, __PRETTY_FUNCTION__)
54 # else
55 # define LOC LAMBDA_LOC(__FUNCTION__, __func__)
56 # endif
57 #else
58 # define LOC lython::CodeLocation::noloc()
59 #endif
60
61 enum LogLevel {
62 Trace,
63 Debug,
64 Info,
65 Warn,
66 Error,
67 Fatal,
68 Off
69 };
70
71 struct Handle {};
72 typedef Handle* LoggerHandle;
73
74 LoggerHandle new_log(const char* name, std::ostream& out);
75
76 class LoggingScope {
77
78 void set_log_level();
79
80 void logerr();
81 void logkwwarn();
82 void logkwdebug();
83 void logkwinfo();
84 void logkwtrace();
85 void logkwfatal();
86
87 template <typename... Args>
88 void _log_message(LogLevel level,
89 CodeLocation const& loc,
90 fmt::string_view fmtstr,
91 const Args&... args) {}
92
93 LoggerHandle logger;
94 };
95
96 void spdlog_log(LogLevel level, const std::string& msg);
97
98 extern const char* log_level_str[];
99 extern const char* trace_start;
100 extern const char* trace_end;
101
102 void set_log_level(LogLevel level, bool enabled);
103
104 bool is_log_enabled(LogLevel level);
105
106 // Show backtrace using spdlog
107 void show_log_backtrace();
108
109 // Show backtrace using execinfo
110 void show_backtrace();
111
112 std::string demangle(std::string const& original_str);
113
114 // retrieve backtrace using execinfo
115 std::vector<std::string> get_backtrace(size_t size);
116
117 // remove namespace info
118 std::string format_function(std::string const&);
119
120 template <typename... Args>
121 void log(LogLevel level, CodeLocation const& loc, fmt::string_view fmtstr, const Args&... args) {
122
123 #if WITH_LOG
124
2/4
✓ Branch 1 taken 2747 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2747 times.
5494 if (!is_log_enabled(level)) {
125 return;
126 }
127
128 10988 auto msg = fmt::format("{}:{} {} - {}",
129 5494 loc.filename,
130
1/2
✓ Branch 1 taken 2747 times.
✗ Branch 2 not taken.
5494 loc.line,
131
1/2
✓ Branch 1 taken 2747 times.
✗ Branch 2 not taken.
5494 format_function(loc.function_name),
132 fmt::format(fmtstr, args...));
133
134
1/2
✓ Branch 1 taken 2747 times.
✗ Branch 2 not taken.
5494 spdlog_log(level, msg);
135 #endif
136 5494 }
137
138 template <typename... Args>
139 void log_kwtrace(LogLevel level,
140 size_t depth,
141 bool end,
142 CodeLocation const& loc,
143 fmt::string_view fmtstr,
144 const Args&... args) {
145
146 #if WITH_LOG
147
2/4
✓ Branch 1 taken 25531 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 25531 times.
50991 if (!is_log_enabled(level)) {
148 return;
149 }
150
151 fmt::string_view msg_fmt = "{:>30}:{:4} {}+-> {}";
152
2/2
✓ Branch 0 taken 3109 times.
✓ Branch 1 taken 22422 times.
50991 if (end) {
153 6218 msg_fmt = "{:>30}:{:4} {}+-< {}";
154 }
155 50991 auto log_message = fmt::format(fmtstr, args...);
156
157
1/2
✓ Branch 2 taken 25531 times.
✗ Branch 3 not taken.
50991 std::string str(depth, ' ');
158
2/2
✓ Branch 0 taken 74286 times.
✓ Branch 1 taken 25531 times.
199280 for (size_t i = 0; i < depth; ++i) {
159
3/4
✓ Branch 0 taken 31712 times.
✓ Branch 1 taken 42574 times.
✓ Branch 3 taken 74286 times.
✗ Branch 4 not taken.
148289 str[i] = i % 2 ? '|' : ':';
160 }
161
162
1/2
✓ Branch 1 taken 25531 times.
✗ Branch 2 not taken.
101982 auto msg = fmt::format(msg_fmt, format_function(loc.function_name), loc.line, str, log_message);
163
164
1/2
✓ Branch 1 taken 25531 times.
✗ Branch 2 not taken.
50991 spdlog_log(level, msg);
165 #endif
166 50991 }
167
168 inline void assert_true(bool cond,
169 char const* message,
170 char const* assert_expr,
171 lython::CodeLocation const& loc) {
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7388 times.
7388 if (!cond) {
173 lython::log(lython::LogLevel::Error,
174 loc,
175 "Assertion errror: {}\n"
176 " - expr: {}",
177 message,
178 assert_expr);
179
180 // lython::show_backkwtrace();
181 assert(cond);
182 }
183 7388 }
184 } // namespace lython
185
186 #define SYM_LOG_HELPER(level, ...) lython::log(level, LOC, __VA_ARGS__)
187 #define kwinfo(...) SYM_LOG_HELPER(lython::LogLevel::Info, __VA_ARGS__)
188 #define kwwarn(...) SYM_LOG_HELPER(lython::LogLevel::Warn, __VA_ARGS__)
189 #define kwdebug(...) SYM_LOG_HELPER(lython::LogLevel::Debug, __VA_ARGS__)
190 #define kwerror(...) SYM_LOG_HELPER(lython::LogLevel::Error, __VA_ARGS__)
191 #define kwfatal(...) SYM_LOG_HELPER(lython::LogLevel::Fatal, __VA_ARGS__)
192
193 #define SYM_LOG_TRACE_HELPER(level, depth, end, ...) \
194 lython::log_kwtrace(level, depth, end, LOC, __VA_ARGS__)
195
196 #define kwtrace(depth, ...) SYM_LOG_TRACE_HELPER(lython::LogLevel::Trace, depth, false, __VA_ARGS__)
197 #define kwtrace_start(depth, ...) \
198 SYM_LOG_TRACE_HELPER(lython::LogLevel::Trace, depth, false, __VA_ARGS__)
199 #define kwtrace_end(depth, ...) \
200 SYM_LOG_TRACE_HELPER(lython::LogLevel::Trace, depth, true, __VA_ARGS__)
201 #endif
202