INSTINCT Code Coverage Report


Directory: src/
File: util/Logger.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 43 72 59.7%
Functions: 5 7 71.4%
Branches: 33 126 26.2%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 #include "Logger.hpp"
10
11 #include "spdlog/sinks/basic_file_sink.h"
12 #include "spdlog/sinks/stdout_color_sinks.h"
13 #include "Logger/dist_filter_sink.hpp"
14
15 #include "internal/gui/NodeEditorApplication.hpp"
16 #include "internal/ConfigManager.hpp"
17 #include "internal/Version.hpp"
18
19 #include <chrono>
20 #include <ctime>
21 #include <iostream>
22
23 #define C_NO "\033[0m"
24
25 #define C_BLACK "\033[0;30m"
26 #define C_DARK_GRAY "\033[1;30m"
27
28 #define C_RED "\033[0;31m"
29 #define C_LIGHT_RED "\033[1;31m"
30
31 #define C_GREEN "\033[0;32m"
32 #define C_LIGHT_GREEN "\033[1;32m"
33
34 #define C_ORANGE "\033[0;33m"
35 #define C_YELLOW "\033[1;33m"
36
37 #define C_BLUE "\033[0;34m"
38 #define C_LIGHT_BLUE "\033[1;34m"
39
40 #define C_PURPLE "\033[0;35m"
41 #define C_LIGHT_PURPLE "\033[1;35m"
42
43 #define C_CYAN "\033[0;36m"
44 #define C_LIGHT_CYAN "\033[1;36m"
45
46 #define C_LIGHT_GRAY "\033[0;37m"
47 #define C_WHITE "\033[1;37m"
48
49 // See https://github.com/gabime/spdlog/wiki/3.-Custom-formatting for formatting options
50 [[maybe_unused]] constexpr const char* logPatternTrace = "[%H:%M:%S.%e] [%^%L%$] [%s:%-3#] [%!()] %v";
51 [[maybe_unused]] constexpr const char* logPatternTraceColor = "[%H:%M:%S.%e] [%^%L%$] [" C_CYAN "%s:%-3#" C_NO "] [" C_ORANGE "%!()" C_NO "] %v";
52 [[maybe_unused]] constexpr const char* logPatternDebug = "[%H:%M:%S.%e] [%^%L%$] [%s:%-3#] %v";
53 [[maybe_unused]] constexpr const char* logPatternDebugColor = "[%H:%M:%S.%e] [%^%L%$] [" C_CYAN "%s:%-3#" C_NO "] %v";
54 [[maybe_unused]] constexpr const char* logPatternInfo = "[%H:%M:%S.%e] [%^%L%$] %v";
55
56 268 Logger::Logger(const std::string& logpath)
57 {
58 #ifndef TESTING
59
60 auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
61 // Only edit if console and file should log different levels
62 console_sink->set_level(spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("console-log-level", "trace")));
63 switch (spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("console-log-level", "trace")))
64 {
65 case spdlog::level::trace:
66 #if LOG_LEVEL == LOG_LEVEL_DATA || LOG_LEVEL == LOG_LEVEL_TRACE
67 console_sink->set_pattern(logPatternTraceColor);
68 break;
69 #endif
70 case spdlog::level::debug:
71 #if LOG_LEVEL == LOG_LEVEL_DEBUG
72 console_sink->set_pattern(logPatternDebugColor);
73 break;
74 #endif
75 case spdlog::level::info:
76 case spdlog::level::warn:
77 case spdlog::level::err:
78 case spdlog::level::critical:
79 console_sink->set_pattern(logPatternInfo);
80 break;
81 case spdlog::level::off:
82 case spdlog::level::n_levels:
83 break;
84 }
85
86 #endif
87
88
1/2
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
268 auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(logpath, true);
89 // Only edit if console and file should log different levels
90
4/8
✓ Branch 2 taken 268 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 268 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 268 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 268 times.
✗ Branch 13 not taken.
1340 file_sink->set_level(spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("file-log-level", "trace")));
91
4/10
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 268 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 268 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 268 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1072 switch (spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("file-log-level", "trace")))
92 {
93 268 case spdlog::level::trace:
94 #if LOG_LEVEL == LOG_LEVEL_DATA || LOG_LEVEL == LOG_LEVEL_TRACE
95 file_sink->set_pattern(logPatternTrace);
96 break;
97 #endif
98 case spdlog::level::debug:
99 #if LOG_LEVEL == LOG_LEVEL_DEBUG
100
2/4
✓ Branch 2 taken 268 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 268 times.
✗ Branch 6 not taken.
536 file_sink->set_pattern(logPatternDebug);
101 268 break;
102 #endif
103 case spdlog::level::info:
104 case spdlog::level::warn:
105 case spdlog::level::err:
106 case spdlog::level::critical:
107 file_sink->set_pattern(logPatternInfo);
108 break;
109 case spdlog::level::off:
110 case spdlog::level::n_levels:
111 break;
112 }
113
114
1/2
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
268 _ringBufferSink = std::make_shared<spdlog::sinks::ringbuffer_sink_mt>(4096);
115
1/2
✓ Branch 2 taken 268 times.
✗ Branch 3 not taken.
268 _ringBufferSink->set_level(spdlog::level::trace);
116
2/4
✓ Branch 2 taken 268 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 268 times.
✗ Branch 6 not taken.
536 _ringBufferSink->set_pattern(logPatternInfo);
117
118 536 std::shared_ptr<spdlog::sinks::dist_sink_mt> dist_filter_sink;
119
3/6
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 268 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 268 times.
536 if (NAV::ConfigManager::HasKey("log-filter"))
120 {
121 dist_filter_sink = std::make_shared<spdlog::sinks::dist_filter_sink_mt>(NAV::ConfigManager::Get<std::string>("log-filter"));
122 }
123 else
124 {
125
1/2
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
268 dist_filter_sink = std::make_shared<spdlog::sinks::dist_sink_mt>();
126 }
127 #ifndef TESTING
128 dist_filter_sink->add_sink(console_sink);
129 #endif
130
1/2
✓ Branch 3 taken 268 times.
✗ Branch 4 not taken.
268 dist_filter_sink->add_sink(file_sink);
131
1/2
✓ Branch 3 taken 268 times.
✗ Branch 4 not taken.
268 dist_filter_sink->add_sink(_ringBufferSink);
132
133 // Set the logger as default logger
134
2/4
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 268 times.
✗ Branch 5 not taken.
268 spdlog::set_default_logger(std::make_shared<spdlog::logger>("multi_sink", dist_filter_sink));
135
136 // Level should be smaller or equal to the level of the sinks
137
4/8
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 268 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 268 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 268 times.
✗ Branch 12 not taken.
1072 spdlog::set_level(spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("global-log-level", "trace")));
138 // Minimum level which automatically triggers a flush
139
4/8
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 268 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 268 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 268 times.
✗ Branch 12 not taken.
804 spdlog::flush_on(spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("flush-log-level", "info")));
140 LOG_TRACE("Setting log flush-on to: {}", NAV::ConfigManager::Get<std::string>("flush-log-level", "info"));
141
142 268 writeHeader();
143
2/4
✓ Branch 1 taken 268 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 268 times.
✗ Branch 5 not taken.
536 if (NAV::ConfigManager::HasKey("log-filter"))
144 {
145 LOG_TRACE("Setting log filter to: {}", NAV::ConfigManager::Get<std::string>("log-filter"));
146 }
147 268 }
148
149 Logger::Logger()
150 {
151 auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
152 console_sink->set_level(spdlog::level::trace);
153
154 // Set the logger as default logger
155 spdlog::set_default_logger(std::make_shared<spdlog::logger>("console_sink", spdlog::sinks_init_list({ console_sink })));
156
157 // Level should be smaller or equal to the level of the sinks
158 spdlog::set_level(spdlog::level::level_enum::trace);
159 // Minimum level which automatically triggers a flush
160 spdlog::flush_on(spdlog::level::trace);
161
162 // See https://github.com/gabime/spdlog/wiki/3.-Custom-formatting for formatting options
163 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
164 spdlog::set_pattern(logPatternTrace);
165 #elif SPDLOG_ACTIVE_LEVEL == SPDLOG_LEVEL_DEBUG
166 spdlog::set_pattern(logPatternDebug);
167 #else
168 spdlog::set_pattern(logPatternInfo);
169 #endif
170
171 writeHeader();
172 }
173
174 268 Logger::~Logger()
175 {
176 268 writeFooter();
177
178 268 spdlog::default_logger()->flush();
179 268 }
180
181 const std::shared_ptr<spdlog::sinks::ringbuffer_sink_mt>& Logger::GetRingBufferSink()
182 {
183 return _ringBufferSink;
184 }
185
186 804 void Logger::writeSeparator() noexcept
187 {
188 1608 LOG_INFO("========================================================================");
189 804 }
190
191 268 void Logger::writeHeader() noexcept
192 {
193 268 auto now = std::chrono::system_clock::now();
194 268 std::time_t now_c = std::chrono::system_clock::to_time_t(now);
195 268 [[maybe_unused]] tm* t = std::localtime(&now_c); // NOLINT(concurrency-mt-unsafe)
196
197 #ifdef NDEBUG
198 LOG_INFO("INSTINCT v{} started in Release on {:04d}-{:02d}-{:02d}", PROJECT_VERSION_STRING, 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
199 #else
200 1340 LOG_INFO("INSTINCT v{} started in Debug on {:04d}-{:02d}-{:02d}", PROJECT_VERSION_STRING, 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
201 #endif
202
203 268 writeSeparator();
204 268 }
205
206 268 void Logger::writeFooter() noexcept
207 {
208 268 writeSeparator();
209
210 268 auto now = std::chrono::system_clock::now();
211 268 std::time_t now_c = std::chrono::system_clock::to_time_t(now);
212 268 [[maybe_unused]] tm* t = std::localtime(&now_c); // NOLINT(concurrency-mt-unsafe)
213
214 268 LOG_INFO("Program finished on {:04d}-{:02d}-{:02d}", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
215
216 268 writeSeparator();
217 268 }
218