ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
statsd.cpp
Go to the documentation of this file.
1#include "esphome/core/log.h"
2
3#include "statsd.h"
4
5#if defined(USE_NETWORK) && !defined(USE_ZEPHYR)
6
7namespace esphome::statsd {
8
9// send UDP packet if we reach 1Kb packed size
10// this is needed since statsD does not support fragmented UDP packets
11static const uint16_t SEND_THRESHOLD = 1024;
12
13ESPHOME_LOG_TAG(TAG, "statsD");
14
16 this->sock_ = esphome::socket::socket_udp_send(AF_INET, 0);
17 if (!this->sock_) {
18 this->mark_failed(LOG_STR("Could not create socket"));
19 return;
20 }
21
22 this->destination_.sin_family = AF_INET;
23 this->destination_.sin_port = htons(this->port_);
24 this->destination_.sin_addr.s_addr = inet_addr(this->host_);
25}
26
28 ESP_LOGCONFIG(TAG,
29 "statsD:\n"
30 " host: %s\n"
31 " port: %d",
32 this->host_, this->port_);
33 if (this->prefix_) {
34 ESP_LOGCONFIG(TAG, " prefix: %s", this->prefix_);
35 }
36
37 ESP_LOGCONFIG(TAG, " metrics:");
38 for (sensors_t s : this->sensors_) {
39 ESP_LOGCONFIG(TAG,
40 " - name: %s\n"
41 " type: %d",
42 s.name, s.type);
43 }
44}
45
47
48#ifdef USE_SENSOR
50 sensors_t s;
51 s.name = name;
52 s.sensor = sensor;
53 s.type = TYPE_SENSOR;
54 this->sensors_.push_back(s);
55}
56#endif
57
58#ifdef USE_BINARY_SENSOR
60 sensors_t s;
61 s.name = name;
62 s.binary_sensor = binary_sensor;
63 s.type = TYPE_BINARY_SENSOR;
64 this->sensors_.push_back(s);
65}
66#endif
67
69 std::string out;
70 out.reserve(SEND_THRESHOLD);
71
72 for (sensors_t s : this->sensors_) {
73 double val = 0;
74 switch (s.type) {
75#ifdef USE_SENSOR
76 case TYPE_SENSOR:
77 if (!s.sensor->has_state()) {
78 continue;
79 }
80 val = s.sensor->state;
81 break;
82#endif
83#ifdef USE_BINARY_SENSOR
84 case TYPE_BINARY_SENSOR:
85 if (!s.binary_sensor->has_state()) {
86 continue;
87 }
88 // map bool to double
89 if (s.binary_sensor->state) {
90 val = 1;
91 }
92 break;
93#endif
94 default:
95 ESP_LOGE(TAG, "type not known, name: %s type: %d", s.name, s.type);
96 continue;
97 }
98
99 // statsD gauge:
100 // https://github.com/statsd/statsd/blob/master/docs/metric_types.md
101 // This implies you can't explicitly set a gauge to a negative number without first setting it to zero.
102 if (val < 0) {
103 if (this->prefix_) {
104 out.append(this->prefix_);
105 out.append(".");
106 }
107 out.append(s.name);
108 out.append(":0|g\n");
109 }
110 if (this->prefix_) {
111 out.append(this->prefix_);
112 out.append(".");
113 }
114 out.append(s.name);
115 // Buffer for ":" + value + "|g\n".
116 // %f with -DBL_MAX can produce up to 321 chars, plus ":" and "|g\n" (4) + null = 326
117 char val_buf[330];
118 buf_append_printf(val_buf, sizeof(val_buf), 0, ":%f|g\n", val);
119 out.append(val_buf);
120
121 if (out.length() > SEND_THRESHOLD) {
122 this->send_(&out);
123 out.clear();
124 }
125 }
126
127 this->send_(&out);
128}
129
130void StatsdComponent::send_(std::string *out) {
131 if (out->empty() || !this->sock_) {
132 return;
133 }
134
135 int n_bytes = this->sock_->sendto(out->c_str(), out->length(), 0, reinterpret_cast<sockaddr *>(&this->destination_),
136 sizeof(this->destination_));
137 if (n_bytes != static_cast<int>(out->length())) {
138 ESP_LOGE(TAG, "Failed to send UDP packed (%d of %d)", n_bytes, out->length());
139 }
140}
141
142} // namespace esphome::statsd
143
144#endif
void mark_failed()
Mark this component as failed.
Base class for all binary_sensor-type classes.
Base-class for all sensors.
Definition sensor.h:47
void register_sensor(const char *name, esphome::sensor::Sensor *sensor)
Definition statsd.cpp:49
void register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor)
Definition statsd.cpp:59
float get_setup_priority() const override
Definition statsd.cpp:46
std::vector< uint8_t > & out
Definition gif.cpp:49
mopeka_std_values val[3]
constexpr float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.h:55
std::unique_ptr< UDPSendSocket > socket_udp_send(int domain, int protocol)
Create a send-only UDP socket (socket_udp_send), a UDP socket with receive support (socket_udp),...
ESPHOME_LOG_TAG(TAG, "statsD")