Sound Byte Libs 1ee2ca6
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
logger.hpp
Go to the documentation of this file.
1/**
2 * @file logger.hpp
3 * @brief Logger class with timestamp provider and output sink
4 *
5 * Output format: I 12345 main.cpp:42| Message
6 *
7 * The Logger class is templated on:
8 * - Output: Sink type with static write(const char*) method
9 * - TimestampProvider: Type with static uint32_t now() method
10 *
11 * Use the macros in macros.hpp for automatic file/line capture.
12 */
13
14#ifndef SBL_LOG_LOGGER_HPP_
15#define SBL_LOG_LOGGER_HPP_
16
17#include <cstdint>
18#include <cstddef>
19#include <sbl/log/format.hpp>
20
21namespace sbl::log {
22
23/**
24 * @brief Log severity levels
25 */
26enum class Level : uint8_t {
27 Off = 0, // Disable all logging
28 Error = 1,
29 Warn = 2,
30 Info = 3,
31 Debug = 4,
32 Trace = 5
33};
34
35/**
36 * @brief Convert level to single character
37 */
38constexpr char level_char(Level level) {
39 switch (level) {
40 case Level::Error: return 'E';
41 case Level::Warn: return 'W';
42 case Level::Info: return 'I';
43 case Level::Debug: return 'D';
44 case Level::Trace: return 'T';
45 default: return '?';
46 }
47}
48
49/**
50 * @brief Default timestamp provider (returns 0)
51 *
52 * Replace with a real implementation that calls your timer driver.
53 */
55 static uint32_t now() { return 0; }
56};
57
58/**
59 * @brief Null output sink (discards all output)
60 */
61struct NullOutput {
62 static void write(const char*) {}
63};
64
65/**
66 * @brief Extract filename from path (compile-time safe)
67 *
68 * Returns pointer to last path component (e.g., "main.cpp" from "/foo/bar/main.cpp")
69 */
70constexpr const char* basename(const char* path) {
71 const char* file = path;
72 while (*path) {
73 if (*path == '/' || *path == '\\') {
74 file = path + 1;
75 }
76 path++;
77 }
78 return file;
79}
80
81/**
82 * @brief Logger class with compile-time level filtering
83 *
84 * @tparam Output Sink type with static write(const char*) method
85 * @tparam TimestampProvider Type with static uint32_t now() method
86 * @tparam MinLevel Minimum level to compile (lower levels are eliminated)
87 */
88template<typename Output, typename TimestampProvider = NullTimestamp, Level MinLevel = Level::Info>
89class Logger {
90public:
91 static constexpr size_t BUFFER_SIZE = 256;
92
93 /**
94 * @brief Log a message with file/line location
95 *
96 * @param level Log severity level
97 * @param file Source file name
98 * @param line Source line number
99 * @param fmt Printf-style format string
100 * @param ... Format arguments
101 */
102 static void log(Level level, const char* file, int line, const char* fmt, ...) {
103 // Runtime level check (compile-time filtering done in macros)
104 if (static_cast<int>(level) > static_cast<int>(MinLevel)) {
105 return;
106 }
107
108 char buffer[BUFFER_SIZE];
109 size_t pos = 0;
110
111 // Format header: I 12345 file.cpp:42|
112 uint32_t timestamp = TimestampProvider::now();
113 pos += format(buffer, BUFFER_SIZE,
114 "%c %u %s:%d| ",
115 level_char(level),
116 timestamp,
117 basename(file),
118 line);
119
120 // Format message
121 if (pos < BUFFER_SIZE - 1) {
122 va_list args;
123 va_start(args, fmt);
124 pos += vformat(buffer + pos, BUFFER_SIZE - pos, fmt, args);
125 va_end(args);
126 }
127
128 // Add newline if space
129 if (pos < BUFFER_SIZE - 1) {
130 buffer[pos++] = '\n';
131 buffer[pos] = '\0';
132 }
133
134 // Output
135 Output::write(buffer);
136 }
137
138 /**
139 * @brief Log without location info (simpler format)
140 *
141 * Format: I 12345| Message
142 */
143 static void log_simple(Level level, const char* fmt, ...) {
144 if (static_cast<int>(level) > static_cast<int>(MinLevel)) {
145 return;
146 }
147
148 char buffer[BUFFER_SIZE];
149 size_t pos = 0;
150
151 uint32_t timestamp = TimestampProvider::now();
152 pos += format(buffer, BUFFER_SIZE,
153 "%c %u| ",
154 level_char(level),
155 timestamp);
156
157 if (pos < BUFFER_SIZE - 1) {
158 va_list args;
159 va_start(args, fmt);
160 pos += vformat(buffer + pos, BUFFER_SIZE - pos, fmt, args);
161 va_end(args);
162 }
163
164 if (pos < BUFFER_SIZE - 1) {
165 buffer[pos++] = '\n';
166 buffer[pos] = '\0';
167 }
168
169 Output::write(buffer);
170 }
171};
172
173} // namespace sbl::log
174
175#endif // SBL_LOG_LOGGER_HPP_
Logger class with compile-time level filtering.
Definition logger.hpp:89
static void log(Level level, const char *file, int line, const char *fmt,...)
Log a message with file/line location.
Definition logger.hpp:102
static constexpr size_t BUFFER_SIZE
Definition logger.hpp:91
static void log_simple(Level level, const char *fmt,...)
Log without location info (simpler format)
Definition logger.hpp:143
Minimal safe string formatting for embedded systems.
constexpr char level_char(Level level)
Convert level to single character.
Definition logger.hpp:38
constexpr const char * basename(const char *path)
Extract filename from path (compile-time safe)
Definition logger.hpp:70
int vformat(char *buf, size_t size, const char *fmt, va_list args)
Format a string into a buffer (vsnprintf-style)
Definition format.hpp:35
int format(char *buf, size_t size, const char *fmt,...)
Format a string into a buffer (snprintf-style)
Definition format.hpp:230
Level
Log severity levels.
Definition logger.hpp:26
Null output sink (discards all output)
Definition logger.hpp:61
static void write(const char *)
Definition logger.hpp:62
Default timestamp provider (returns 0)
Definition logger.hpp:54
static uint32_t now()
Definition logger.hpp:55