ESPHome 2026.1.0-dev
Loading...
Searching...
No Matches
esphome_syslog.cpp
Go to the documentation of this file.
1#include "esphome_syslog.h"
2
5#include "esphome/core/time.h"
6
7namespace esphome::syslog {
8
9// Map log levels to syslog severity using an array, indexed by ESPHome log level (1-7)
11 3, // NONE
12 3, // ERROR
13 4, // WARN
14 5, // INFO
15 6, // CONFIG
16 7, // DEBUG
17 7, // VERBOSE
18 7 // VERY_VERBOSE
19};
20
22
23void Syslog::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) {
24 this->log_(level, tag, message, message_len);
25}
26
27void Syslog::log_(const int level, const char *tag, const char *message, size_t message_len) const {
28 if (level > this->log_level_)
29 return;
30 // Syslog PRI calculation: facility * 8 + severity
31 int severity = 7;
32 if ((unsigned) level <= 7) {
33 severity = LOG_LEVEL_TO_SYSLOG_SEVERITY[level];
34 }
35 int pri = this->facility_ * 8 + severity;
36
37 size_t len = message_len;
38 // remove color formatting
39 if (this->strip_ && message[0] == 0x1B && len > 11) {
40 message += 7;
41 len -= 11;
42 }
43
44 // Build syslog packet on stack (508 bytes chosen as practical limit for syslog over UDP)
45 char packet[508];
46 size_t offset = 0;
47 size_t remaining = sizeof(packet);
48
49 // Write PRI - abort if this fails as packet would be malformed
50 int ret = snprintf(packet, remaining, "<%d>", pri);
51 if (ret <= 0 || static_cast<size_t>(ret) >= remaining) {
52 return;
53 }
54 offset = ret;
55 remaining -= ret;
56
57 // Write timestamp directly into packet (RFC 5424: use "-" if time not valid or strftime fails)
58 auto now = this->time_->now();
59 size_t ts_written = now.is_valid() ? now.strftime(packet + offset, remaining, "%b %e %H:%M:%S") : 0;
60 if (ts_written > 0) {
61 offset += ts_written;
62 remaining -= ts_written;
63 } else if (remaining > 0) {
64 packet[offset++] = '-';
65 remaining--;
66 }
67
68 // Write hostname, tag, and message
69 ret = snprintf(packet + offset, remaining, " %s %s: %.*s", App.get_name().c_str(), tag, (int) len, message);
70 if (ret > 0) {
71 // snprintf returns chars that would be written; clamp to actual buffer space
72 offset += std::min(static_cast<size_t>(ret), remaining > 0 ? remaining - 1 : 0);
73 }
74
75 if (offset > 0) {
76 this->parent_->send_packet(reinterpret_cast<const uint8_t *>(packet), offset);
77 }
78}
79
80} // namespace esphome::syslog
const std::string & get_name() const
Get the name of this Application set by pre_setup().
void add_log_listener(LogListener *listener)
Register a log listener to receive log messages.
Definition logger.h:207
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override
time::RealTimeClock * time_
void log_(int level, const char *tag, const char *message, size_t message_len) const
ESPTime now()
Get the time in the currently defined timezone.
void send_packet(const uint8_t *data, size_t size)
const char * message
Definition component.cpp:38
Logger * global_logger
Definition logger.cpp:297
constexpr int LOG_LEVEL_TO_SYSLOG_SEVERITY[]
std::string size_t len
Definition helpers.h:533
Application App
Global storage of Application pointer - only one Application can exist.
bool is_valid() const
Check if this ESPTime is valid (all fields in range and year is greater than 2018)
Definition time.h:61