0.4.1
Loading...
Searching...
No Matches
Logger.cpp
Go to the documentation of this file.
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"
14
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
56Logger::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 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 file_sink->set_level(spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("file-log-level", "trace")));
91 switch (spdlog::level::from_str(NAV::ConfigManager::Get<std::string>("file-log-level", "trace")))
92 {
93 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 file_sink->set_pattern(logPatternDebug);
101 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 _ringBufferSink = std::make_shared<spdlog::sinks::ringbuffer_sink_mt>(4096);
115 _ringBufferSink->set_level(spdlog::level::trace);
116 _ringBufferSink->set_pattern(logPatternInfo);
117
118 std::shared_ptr<spdlog::sinks::dist_sink_mt> dist_filter_sink;
119 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 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 dist_filter_sink->add_sink(file_sink);
131 dist_filter_sink->add_sink(_ringBufferSink);
132
133 // Set the logger as default logger
134 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 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 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 writeHeader();
143 if (NAV::ConfigManager::HasKey("log-filter"))
144 {
145 LOG_TRACE("Setting log filter to: {}", NAV::ConfigManager::Get<std::string>("log-filter"));
146 }
147}
148
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
175{
176 writeFooter();
177
178 spdlog::default_logger()->flush();
179}
180
181const std::shared_ptr<spdlog::sinks::ringbuffer_sink_mt>& Logger::GetRingBufferSink()
182{
183 return _ringBufferSink;
184}
185
187{
188 LOG_INFO("========================================================================");
189}
190
191void Logger::writeHeader() noexcept
192{
193 auto now = std::chrono::system_clock::now();
194 std::time_t now_c = std::chrono::system_clock::to_time_t(now);
195 [[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 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
204}
205
206void Logger::writeFooter() noexcept
207{
209
210 auto now = std::chrono::system_clock::now();
211 std::time_t now_c = std::chrono::system_clock::to_time_t(now);
212 [[maybe_unused]] tm* t = std::localtime(&now_c); // NOLINT(concurrency-mt-unsafe)
213
214 LOG_INFO("Program finished on {:04d}-{:02d}-{:02d}", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
215
217}
Config management for the Project.
#define C_CYAN
Definition Logger.cpp:43
#define C_NO
Definition Logger.cpp:23
constexpr const char * logPatternDebugColor
Definition Logger.cpp:53
constexpr const char * logPatternDebug
Definition Logger.cpp:52
constexpr const char * logPatternInfo
Definition Logger.cpp:54
constexpr const char * logPatternTraceColor
Definition Logger.cpp:51
#define C_ORANGE
Definition Logger.cpp:34
constexpr const char * logPatternTrace
Definition Logger.cpp:50
Utility class for logging to console and file.
#define LOG_INFO
Info to the user on the state of the program.
Definition Logger.hpp:69
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Definition Logger.hpp:65
Provides the version of the project.
#define PROJECT_VERSION_STRING
Project Version String in the form "major.minor.patch".
Definition Version.hpp:32
static const std::shared_ptr< spdlog::sinks::ringbuffer_sink_mt > & GetRingBufferSink()
Returns the ring buffer sink.
Definition Logger.cpp:181
static void writeFooter() noexcept
Writes the logging footer.
Definition Logger.cpp:206
static void writeHeader() noexcept
Writes the logging header.
Definition Logger.cpp:191
static std::shared_ptr< spdlog::sinks::ringbuffer_sink_mt > _ringBufferSink
Ring buffer sink.
Definition Logger.hpp:112
Logger()
Default constructor.
Definition Logger.cpp:149
~Logger()
Destructor.
Definition Logger.cpp:174
static void writeSeparator() noexcept
Writes a separation line to the console only.
Definition Logger.cpp:186
Distribution sink with filter option. Stores a vector of sinks which get called when log is called.
const T & Get(const std::string &key, const T &&defaultValue)
Retrieves the value of a corresponding key from the configuration, if one exists.
bool HasKey(const std::string &key)
Checks if a corresponding key exists in the configuration.