16#if DETWS_ENABLE_STATSD
24size_t u64_str(
char *b, uint64_t v)
35 tmp[n++] = (char)(
'0' + v % 10);
38 for (
size_t i = 0; i < n; i++)
39 b[i] = tmp[n - 1 - i];
44size_t i64_str(
char *b, int64_t v)
49 return 1 + u64_str(b + 1, (uint64_t)(-(v + 1)) + 1);
51 return u64_str(b, (uint64_t)v);
55size_t i64_delta_str(
char *b, int64_t v)
60 return 1 + u64_str(b + 1, (uint64_t)v);
66size_t rate_str(
char *b,
float r)
68 if (r >= 1.0f || r <= 0.0f)
70 int m = (int)(r * 1000.0f + 0.5f);
77 b[2] = (char)(
'0' + (m / 100) % 10);
78 b[3] = (char)(
'0' + (m / 10) % 10);
79 b[4] = (char)(
'0' + m % 10);
81 while (len > 3 && b[len - 1] ==
'0')
87bool app(
char *out,
size_t cap,
size_t *pos,
const char *s,
size_t n)
91 memcpy(out + *pos, s, n);
100 if (!out || cap == 0 || !name || !name[0] || !value)
108 if (!app(out, cap, &pos, name, strnlen(name, cap)) || !app(out, cap, &pos,
":", 1) ||
109 !app(out, cap, &pos, value, strnlen(value, cap)) || !app(out, cap, &pos,
"|", 1))
113 if (!app(out, cap, &pos,
"ms", 2))
116 else if (!app(out, cap, &pos, &t, 1))
120 size_t rn = rate_str(rbuf, rate);
121 if (rn && (!app(out, cap, &pos,
"|@", 2) || !app(out, cap, &pos, rbuf, rn)))
123 if (tags && tags[0] && (!app(out, cap, &pos,
"|#", 2) || !app(out, cap, &pos, tags, strnlen(tags, cap))))
148void emit(
const StatsdCtx &c,
const char *name,
const char *value,
StatsdType type,
float rate)
153 size_t n =
statsd_format(line,
sizeof(line), name, value, type, rate, c.tags[0] ? c.tags : nullptr);
159void statsd_begin(
const char *host, uint16_t port,
const char *global_tags)
163 s_statsd.ready =
false;
166 strncpy(s_statsd.host, host,
sizeof(s_statsd.host) - 1);
167 s_statsd.host[
sizeof(s_statsd.host) - 1] =
'\0';
171 strncpy(s_statsd.tags, global_tags,
sizeof(s_statsd.tags) - 1);
172 s_statsd.tags[
sizeof(s_statsd.tags) - 1] =
'\0';
175 s_statsd.tags[0] =
'\0';
176 s_statsd.ready =
true;
182 v[i64_str(v, delta)] =
'\0';
189 v[i64_str(v, delta)] =
'\0';
196 v[i64_str(v, value)] =
'\0';
203 v[i64_delta_str(v, delta)] =
'\0';
210 v[u64_str(v, ms)] =
'\0';
214void statsd_set(
const char *name,
const char *member)
User-facing configuration for DeterministicESPAsyncWebServer.
#define DETWS_STATSD_PORT
Default StatsD collector UDP port (StatsD/Graphite standard).
#define DETWS_STATSD_LINE_MAX
Stack buffer for one StatsD line (bytes; caps metric name + value + tags).
StatsD metrics client - push counters/gauges/timings/sets to a StatsD collector.
void statsd_gauge_delta(const char *name, int64_t delta)
Adjust a gauge by a signed delta (sent as a +/- gauge update).
void statsd_begin(const char *host, uint16_t port, const char *global_tags)
Point the client at a collector and set optional global tags (added to every metric).
void statsd_count(const char *name, int64_t delta)
Increment a counter by delta (may be negative).
void statsd_timing(const char *name, uint32_t ms)
Record a timing/duration of ms milliseconds.
StatsdType
StatsD metric type codes (the token after the |).
@ STATSD_TIMING
emitted as "ms"
void statsd_set(const char *name, const char *member)
Add a unique member to a set (counts distinct values server-side).
size_t statsd_format(char *out, size_t cap, const char *name, const char *value, StatsdType type, float rate, const char *tags)
Format one StatsD line: name:value|type[|@rate][|#tags]. Pure - no I/O.
void statsd_gauge(const char *name, int64_t value)
Set a gauge to an absolute value.
void statsd_count_sampled(const char *name, int64_t delta, float rate)
Increment a counter, annotated with sample rate (0,1] so the server scales up.
bool det_udp_sendto(const char *dst_ip, uint16_t dst_port, const uint8_t *data, size_t len)
Send a UDP datagram to an arbitrary destination (outbound client).
Layer 4 (Transport) - connectionless UDP datagram service.