idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
log.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
6#include "sdkconfig.h"
7#ifndef CONFIG_IDFXX_STD_FORMAT
8#error "idfxx_log requires CONFIG_IDFXX_STD_FORMAT to be enabled (menuconfig -> IDFXX -> Enable std::format support)"
9#endif
10
33#include <algorithm>
34#include <cstddef>
35#include <cstdint>
36#include <esp_log.h>
37#include <format>
38#include <string>
39#include <string_view>
40#include <utility>
41
42namespace idfxx::log {
43
52enum class level : uint8_t {
53 none = ESP_LOG_NONE,
54 error = ESP_LOG_ERROR,
55 warn = ESP_LOG_WARN,
56 info = ESP_LOG_INFO,
57 debug = ESP_LOG_DEBUG,
58 verbose = ESP_LOG_VERBOSE,
59};
60
72void log(level lvl, const char* tag, std::string_view msg);
73
87template<typename... Args>
88void log(level lvl, const char* tag, std::format_string<Args...> fmt, Args&&... args) {
89 if (static_cast<int>(lvl) > LOG_LOCAL_LEVEL) {
90 return;
91 }
92 if (esp_log_level_get(tag) < static_cast<esp_log_level_t>(lvl)) {
93 return;
94 }
95 log(lvl, tag, std::format(fmt, std::forward<Args>(args)...));
96}
97
107template<typename... Args>
108void error(const char* tag, std::format_string<Args...> fmt, Args&&... args) {
109 log(level::error, tag, fmt, std::forward<Args>(args)...);
110}
111
119inline void error(const char* tag, std::string_view msg) {
120 log(level::error, tag, msg);
121}
122
132template<typename... Args>
133void warn(const char* tag, std::format_string<Args...> fmt, Args&&... args) {
134 log(level::warn, tag, fmt, std::forward<Args>(args)...);
135}
136
144inline void warn(const char* tag, std::string_view msg) {
145 log(level::warn, tag, msg);
146}
147
157template<typename... Args>
158void info(const char* tag, std::format_string<Args...> fmt, Args&&... args) {
159 log(level::info, tag, fmt, std::forward<Args>(args)...);
160}
161
169inline void info(const char* tag, std::string_view msg) {
170 log(level::info, tag, msg);
171}
172
182template<typename... Args>
183void debug(const char* tag, std::format_string<Args...> fmt, Args&&... args) {
184 log(level::debug, tag, fmt, std::forward<Args>(args)...);
185}
186
194inline void debug(const char* tag, std::string_view msg) {
195 log(level::debug, tag, msg);
196}
197
207template<typename... Args>
208void verbose(const char* tag, std::format_string<Args...> fmt, Args&&... args) {
209 log(level::verbose, tag, fmt, std::forward<Args>(args)...);
210}
211
219inline void verbose(const char* tag, std::string_view msg) {
220 log(level::verbose, tag, msg);
221}
222
233void set_level(const char* tag, level lvl);
234
244
256void buffer_hex(level lvl, const char* tag, const void* buffer, size_t length);
257
270void buffer_char(level lvl, const char* tag, const void* buffer, size_t length);
271
284void buffer_hex_dump(level lvl, const char* tag, const void* buffer, size_t length);
285
304class logger {
305public:
312 constexpr explicit logger(const char* tag) noexcept
313 : _tag(tag) {}
314
320 [[nodiscard]] constexpr const char* tag() const noexcept { return _tag; }
321
330 template<typename... Args>
331 void log(level lvl, std::format_string<Args...> fmt, Args&&... args) const {
332 idfxx::log::log(lvl, _tag, fmt, std::forward<Args>(args)...);
333 }
334
341 void log(level lvl, std::string_view msg) const { idfxx::log::log(lvl, _tag, msg); }
342
350 template<typename... Args>
351 void error(std::format_string<Args...> fmt, Args&&... args) const {
352 idfxx::log::error(_tag, fmt, std::forward<Args>(args)...);
353 }
354
360 void error(std::string_view msg) const { idfxx::log::error(_tag, msg); }
361
369 template<typename... Args>
370 void warn(std::format_string<Args...> fmt, Args&&... args) const {
371 idfxx::log::warn(_tag, fmt, std::forward<Args>(args)...);
372 }
373
379 void warn(std::string_view msg) const { idfxx::log::warn(_tag, msg); }
380
388 template<typename... Args>
389 void info(std::format_string<Args...> fmt, Args&&... args) const {
390 idfxx::log::info(_tag, fmt, std::forward<Args>(args)...);
391 }
392
398 void info(std::string_view msg) const { idfxx::log::info(_tag, msg); }
399
407 template<typename... Args>
408 void debug(std::format_string<Args...> fmt, Args&&... args) const {
409 idfxx::log::debug(_tag, fmt, std::forward<Args>(args)...);
410 }
411
417 void debug(std::string_view msg) const { idfxx::log::debug(_tag, msg); }
418
426 template<typename... Args>
427 void verbose(std::format_string<Args...> fmt, Args&&... args) const {
428 idfxx::log::verbose(_tag, fmt, std::forward<Args>(args)...);
429 }
430
436 void verbose(std::string_view msg) const { idfxx::log::verbose(_tag, msg); }
437
446 void set_level(level lvl) const;
447
455 void buffer_hex(level lvl, const void* buffer, size_t length) const {
456 idfxx::log::buffer_hex(lvl, _tag, buffer, length);
457 }
458
466 void buffer_char(level lvl, const void* buffer, size_t length) const {
467 idfxx::log::buffer_char(lvl, _tag, buffer, length);
468 }
469
477 void buffer_hex_dump(level lvl, const void* buffer, size_t length) const {
478 idfxx::log::buffer_hex_dump(lvl, _tag, buffer, length);
479 }
480
481private:
482 const char* _tag;
483};
484
485} // namespace idfxx::log
486
487namespace idfxx {
488
496[[nodiscard]] inline std::string to_string(log::level lvl) {
497 switch (lvl) {
498 case log::level::none:
499 return "NONE";
501 return "ERROR";
502 case log::level::warn:
503 return "WARN";
504 case log::level::info:
505 return "INFO";
507 return "DEBUG";
509 return "VERBOSE";
510 default:
511 return "unknown(" + std::to_string(static_cast<unsigned int>(lvl)) + ")";
512 }
513}
514
515} // namespace idfxx
516
520namespace std {
521template<>
522struct formatter<idfxx::log::level> {
523 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
524
525 template<typename FormatContext>
526 auto format(idfxx::log::level lvl, FormatContext& ctx) const {
527 auto s = idfxx::to_string(lvl);
528 return std::copy(s.begin(), s.end(), ctx.out());
529 }
530};
531} // namespace std
534// NOLINTBEGIN(cppcoreguidelines-macro-usage)
535
546#define IDFXX_LOGE(tag, fmt, ...) \
547 do { \
548 if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { \
549 idfxx::log::error(tag, fmt __VA_OPT__(, ) __VA_ARGS__); \
550 } \
551 } while (0)
552
560#define IDFXX_LOGW(tag, fmt, ...) \
561 do { \
562 if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { \
563 idfxx::log::warn(tag, fmt __VA_OPT__(, ) __VA_ARGS__); \
564 } \
565 } while (0)
566
574#define IDFXX_LOGI(tag, fmt, ...) \
575 do { \
576 if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { \
577 idfxx::log::info(tag, fmt __VA_OPT__(, ) __VA_ARGS__); \
578 } \
579 } while (0)
580
588#define IDFXX_LOGD(tag, fmt, ...) \
589 do { \
590 if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { \
591 idfxx::log::debug(tag, fmt __VA_OPT__(, ) __VA_ARGS__); \
592 } \
593 } while (0)
594
602#define IDFXX_LOGV(tag, fmt, ...) \
603 do { \
604 if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { \
605 idfxx::log::verbose(tag, fmt __VA_OPT__(, ) __VA_ARGS__); \
606 } \
607 } while (0)
608
609// NOLINTEND(cppcoreguidelines-macro-usage)
Lightweight logger bound to a specific tag.
Definition log.hpp:304
void error(std::string_view msg) const
Log a pre-formatted message at error level.
Definition log.hpp:360
void buffer_char(level lvl, const void *buffer, size_t length) const
Log a buffer as printable characters.
Definition log.hpp:466
void debug(std::string_view msg) const
Log a pre-formatted message at debug level.
Definition log.hpp:417
void debug(std::format_string< Args... > fmt, Args &&... args) const
Log a message at debug level.
Definition log.hpp:408
void info(std::string_view msg) const
Log a pre-formatted message at info level.
Definition log.hpp:398
void log(level lvl, std::format_string< Args... > fmt, Args &&... args) const
Log a message at the specified level.
Definition log.hpp:331
void buffer_hex(level lvl, const void *buffer, size_t length) const
Log a buffer as hexadecimal bytes.
Definition log.hpp:455
void verbose(std::string_view msg) const
Log a pre-formatted message at verbose level.
Definition log.hpp:436
void log(level lvl, std::string_view msg) const
Log a pre-formatted message at the specified level.
Definition log.hpp:341
void warn(std::string_view msg) const
Log a pre-formatted message at warning level.
Definition log.hpp:379
void error(std::format_string< Args... > fmt, Args &&... args) const
Log a message at error level.
Definition log.hpp:351
void buffer_hex_dump(level lvl, const void *buffer, size_t length) const
Log a buffer as a formatted hex dump.
Definition log.hpp:477
void warn(std::format_string< Args... > fmt, Args &&... args) const
Log a message at warning level.
Definition log.hpp:370
void verbose(std::format_string< Args... > fmt, Args &&... args) const
Log a message at verbose level.
Definition log.hpp:427
constexpr const char * tag() const noexcept
Get the tag associated with this logger.
Definition log.hpp:320
constexpr logger(const char *tag) noexcept
Construct a logger with the given tag.
Definition log.hpp:312
void info(std::format_string< Args... > fmt, Args &&... args) const
Log a message at info level.
Definition log.hpp:389
void set_level(level lvl) const
Set the runtime log level for this logger's tag.
std::string to_string(core_id c)
Returns a string representation of a CPU core identifier.
Definition cpu.hpp:52
void buffer_hex_dump(level lvl, const char *tag, const void *buffer, size_t length)
Log a buffer as a formatted hex dump.
void set_level(const char *tag, level lvl)
Set the runtime log level for a specific tag.
void log(level lvl, const char *tag, std::string_view msg)
Log a pre-formatted message at the specified level.
void set_default_level(level lvl)
Set the default log level for all tags.
void buffer_char(level lvl, const char *tag, const void *buffer, size_t length)
Log a buffer as printable characters.
level
Log severity level.
Definition log.hpp:52
@ warn
Warning conditions that may indicate problems.
@ verbose
Highly detailed trace information.
@ none
No log output.
@ debug
Detailed information for debugging.
@ info
Informational messages about normal operation.
@ error
Critical errors requiring immediate attention.
void buffer_hex(level lvl, const char *tag, const void *buffer, size_t length)
Log a buffer as hexadecimal bytes.