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++)
40 b[i] = tmp[n - 1 - i];
46size_t i64_str(
char *b, int64_t v)
51 return 1 + u64_str(b + 1, (uint64_t)(-(v + 1)) + 1);
53 return u64_str(b, (uint64_t)v);
57size_t i64_delta_str(
char *b, int64_t v)
62 return 1 + u64_str(b + 1, (uint64_t)v);
68size_t rate_str(
char *b,
float r)
70 if (r >= 1.0f || r <= 0.0f)
74 int m = (int)(r * 1000.0f + 0.5f);
85 b[2] = (char)(
'0' + (m / 100) % 10);
86 b[3] = (char)(
'0' + (m / 10) % 10);
87 b[4] = (char)(
'0' + m % 10);
89 while (len > 3 && b[len - 1] ==
'0')
97bool app(
char *out,
size_t cap,
size_t *pos,
const char *s,
size_t n)
103 memcpy(out + *pos, s, n);
112 if (!out || cap == 0 || !name || !name[0] || !value)
124 if (!app(out, cap, &pos, name, strnlen(name, cap)) || !app(out, cap, &pos,
":", 1) ||
125 !app(out, cap, &pos, value, strnlen(value, cap)) || !app(out, cap, &pos,
"|", 1))
131 if (!app(out, cap, &pos,
"ms", 2))
136 else if (!app(out, cap, &pos, &t, 1))
142 size_t rn = rate_str(rbuf, rate);
143 if (rn && (!app(out, cap, &pos,
"|@", 2) || !app(out, cap, &pos, rbuf, rn)))
147 if (tags && tags[0] && (!app(out, cap, &pos,
"|#", 2) || !app(out, cap, &pos, tags, strnlen(tags, cap))))
174void emit(
const StatsdCtx &c,
const char *name,
const char *value,
StatsdType type,
float rate)
181 size_t n =
pc_statsd_format(line,
sizeof(line), name, value, type, rate, c.tags[0] ? c.tags : nullptr);
189void pc_statsd_begin(
const char *host, uint16_t port,
const char *global_tags)
193 s_statsd.ready =
false;
196 strncpy(s_statsd.host, host,
sizeof(s_statsd.host) - 1);
197 s_statsd.host[
sizeof(s_statsd.host) - 1] =
'\0';
201 strncpy(s_statsd.tags, global_tags,
sizeof(s_statsd.tags) - 1);
202 s_statsd.tags[
sizeof(s_statsd.tags) - 1] =
'\0';
206 s_statsd.tags[0] =
'\0';
208 s_statsd.ready =
true;
214 v[i64_str(v, delta)] =
'\0';
221 v[i64_str(v, delta)] =
'\0';
228 v[i64_str(v, value)] =
'\0';
235 v[i64_delta_str(v, delta)] =
'\0';
242 v[u64_str(v, ms)] =
'\0';
User-facing configuration for ProtoCore.
#define PC_STATSD_LINE_MAX
Stack buffer for one StatsD line (bytes; caps metric name + value + tags).
#define PC_STATSD_PORT
Default StatsD collector UDP port (StatsD/Graphite standard).
StatsD metrics client - push counters/gauges/timings/sets to a StatsD collector.
void pc_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 pc_statsd_count(const char *name, int64_t delta)
Increment a counter by delta (may be negative).
void pc_statsd_gauge_delta(const char *name, int64_t delta)
Adjust a gauge by a signed delta (sent as a +/- gauge update).
void pc_statsd_set(const char *name, const char *member)
Add a unique member to a set (counts distinct values server-side).
void pc_statsd_timing(const char *name, uint32_t ms)
Record a timing/duration of ms milliseconds.
void pc_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.
StatsdType
StatsD metric type codes (the token after the |).
@ STATSD_TIMING
emitted as "ms"
void pc_statsd_gauge(const char *name, int64_t value)
Set a gauge to an absolute value.
size_t pc_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.
bool pc_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.