add ACLK stats per cloud query type (#10602)
* add stats per cloud query type
Timotej S committed
Feb 26, 2021 at 14:24 UTC
9cb6e7f4107db983a490da87383ba703ec38a840
5 files changed
+117
-14
aclk/legacy/aclk_query.c
+1
@@ -62,6 +62,7 @@ static void aclk_query_free(struct aclk_query *this_query)
62
freez(this_query->query);
63
if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2) {
64
struct aclk_cloud_req_v2 *del = (struct aclk_cloud_req_v2 *)this_query->data;
65
+ freez(del->query_endpoint);
66
freez(del->data);
67
freez(del);
68
}
aclk/legacy/aclk_query.h
+1
@@ -31,6 +31,7 @@ struct aclk_query_threads {
31
struct aclk_cloud_req_v2 {
32
char *data;
33
RRDHOST *host;
34
+ char *query_endpoint;
35
};
36
37
void *aclk_query_main_thread(void *ptr);
aclk/legacy/aclk_rx_msgs.c
+29
-7
@@ -25,7 +25,7 @@ static inline int aclk_extract_v2_data(char *payload, char **data)
25
#define STRNCMP_CONSTANT_PREFIX(str, const_pref) strncmp(str, const_pref, strlen(const_pref))
26
static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req, struct aclk_request *req)
27
{
28
- const char *start, *end, *ptr;
28
+ const char *start, *end, *ptr, *query_type;
29
char uuid_str[UUID_STR_LEN];
30
uuid_t uuid;
31
@@ -66,6 +66,8 @@ static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req,
66
error("Only accepting requests that start with \"%s\" from CLOUD.", ACLK_CLOUD_REQ_V2_PREFIX);
67
return 1;
68
}
69
+ ptr += strlen(ACLK_CLOUD_REQ_V2_PREFIX);
70
+ query_type = ptr;
71
72
if(!(end = strstr(ptr, " HTTP/1.1\x0D\x0A"))) {
73
errno = 0;
@@ -73,6 +75,11 @@ static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req,
75
return 1;
76
}
77
78
+ if(!(ptr = strchr(ptr, '?')) || ptr > end)
79
+ ptr = end;
80
+ cloud_req->query_endpoint = mallocz((ptr - query_type) + 1);
81
+ strncpyz(cloud_req->query_endpoint, query_type, ptr - query_type);
82
+
83
req->payload = mallocz((end - start) + 1);
84
strncpyz(req->payload, start, end - start);
85
@@ -122,6 +129,13 @@ static int aclk_handle_cloud_request_v1(struct aclk_request *cloud_to_agent, cha
129
if (unlikely(aclk_queue_query(cloud_to_agent->callback_topic, NULL, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0, ACLK_CMD_CLOUD)))
130
debug(D_ACLK, "ACLK failed to queue incoming \"http\" message");
131
132
+ if (aclk_stats_enabled) {
133
+ ACLK_STATS_LOCK;
134
+ aclk_metrics_per_sample.cloud_req_v1++;
135
+ aclk_metrics_per_sample.cloud_req_ok++;
136
+ ACLK_STATS_UNLOCK;
137
+ }
138
+
139
return 0;
140
}
141
@@ -131,6 +145,7 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
145
146
struct aclk_cloud_req_v2 *cloud_req;
147
char *data;
148
+ int stat_idx;
149
150
errno = 0;
151
if (cloud_to_agent->version < ACLK_V_COMPRESSION) {
@@ -165,6 +180,10 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
180
goto cleanup;
181
}
182
183
+ // we do this here due to cloud_req being taken over by query thread
184
+ // which if crazy quick can free it after aclk_queue_query
185
+ stat_idx = aclk_cloud_req_type_to_idx(cloud_req->query_endpoint);
186
+
187
// aclk_queue_query takes ownership of data pointer
188
if (unlikely(aclk_queue_query(
189
cloud_to_agent->callback_topic, cloud_req, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
@@ -173,8 +192,17 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
192
goto cleanup;
193
}
194
195
+ if (aclk_stats_enabled) {
196
+ ACLK_STATS_LOCK;
197
+ aclk_metrics_per_sample.cloud_req_v2++;
198
+ aclk_metrics_per_sample.cloud_req_ok++;
199
+ aclk_metrics_per_sample.cloud_req_by_type[stat_idx]++;
200
+ ACLK_STATS_UNLOCK;
201
+ }
202
+
203
return 0;
204
cleanup:
205
+ freez(cloud_req->query_endpoint);
206
freez(cloud_req->data);
207
freez(cloud_req);
208
return 1;
@@ -289,12 +317,6 @@ int aclk_handle_cloud_message(char *payload)
317
struct aclk_request cloud_to_agent;
318
memset(&cloud_to_agent, 0, sizeof(struct aclk_request));
319
292
- if (aclk_stats_enabled) {
293
- ACLK_STATS_LOCK;
294
- aclk_metrics_per_sample.cloud_req_recvd++;
295
- ACLK_STATS_UNLOCK;
296
- }
297
-
320
if (unlikely(!payload)) {
321
errno = 0;
322
error("ACLK incoming message is empty");
aclk/legacy/aclk_stats.c
+75
-6
@@ -162,7 +162,7 @@ static void aclk_stats_read_q(struct aclk_metrics_per_sample *per_sample)
162
static void aclk_stats_cloud_req(struct aclk_metrics_per_sample *per_sample)
163
{
164
static RRDSET *st = NULL;
165
- static RRDDIM *rd_rq_rcvd = NULL;
165
+ static RRDDIM *rd_rq_ok = NULL;
166
static RRDDIM *rd_rq_err = NULL;
167
168
if (unlikely(!st)) {
@@ -170,17 +170,82 @@ static void aclk_stats_cloud_req(struct aclk_metrics_per_sample *per_sample)
170
"netdata", "aclk_cloud_req", NULL, "aclk", NULL, "Requests received from cloud", "req/s",
171
"netdata", "stats", 200005, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
172
173
- rd_rq_rcvd = rrddim_add(st, "received", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
174
- rd_rq_err = rrddim_add(st, "malformed", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
173
+ rd_rq_ok = rrddim_add(st, "accepted", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
174
+ rd_rq_err = rrddim_add(st, "rejected", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
175
} else
176
rrdset_next(st);
177
178
- rrddim_set_by_pointer(st, rd_rq_rcvd, per_sample->cloud_req_recvd - per_sample->cloud_req_err);
178
+ rrddim_set_by_pointer(st, rd_rq_ok, per_sample->cloud_req_ok);
179
rrddim_set_by_pointer(st, rd_rq_err, per_sample->cloud_req_err);
180
181
rrdset_done(st);
182
}
183
184
+static void aclk_stats_cloud_req_version(struct aclk_metrics_per_sample *per_sample)
185
+{
186
+ static RRDSET *st = NULL;
187
+ static RRDDIM *rd_rq_v1 = NULL;
188
+ static RRDDIM *rd_rq_v2 = NULL;
189
+
190
+ if (unlikely(!st)) {
191
+ st = rrdset_create_localhost(
192
+ "netdata", "aclk_cloud_req_version", NULL, "aclk", NULL, "Requests received from cloud by their version", "req/s",
193
+ "netdata", "stats", 200006, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
194
+
195
+ rd_rq_v1 = rrddim_add(st, "v1", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
196
+ rd_rq_v2 = rrddim_add(st, "v2+", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
197
+ } else
198
+ rrdset_next(st);
199
+
200
+ rrddim_set_by_pointer(st, rd_rq_v1, per_sample->cloud_req_v1);
201
+ rrddim_set_by_pointer(st, rd_rq_v2, per_sample->cloud_req_v2);
202
+
203
+ rrdset_done(st);
204
+}
205
+
206
+static char *cloud_req_type_names[ACLK_STATS_CLOUD_REQ_TYPE_CNT] = {
207
+ "other",
208
+ "info",
209
+ "data",
210
+ "alarms",
211
+ "alarm_log",
212
+ "chart",
213
+ "charts"
214
+ // if you change update:
215
+ // #define ACLK_STATS_CLOUD_REQ_TYPE_CNT 7
216
+};
217
+
218
+int aclk_cloud_req_type_to_idx(const char *name)
219
+{
220
+ for (int i = 1; i < ACLK_STATS_CLOUD_REQ_TYPE_CNT; i++)
221
+ if (!strcmp(cloud_req_type_names[i], name))
222
+ return i;
223
+ return 0;
224
+}
225
+
226
+static void aclk_stats_cloud_req_cmd(struct aclk_metrics_per_sample *per_sample)
227
+{
228
+ static RRDSET *st;
229
+ static int initialized = 0;
230
+ static RRDDIM *rd_rq_types[ACLK_STATS_CLOUD_REQ_TYPE_CNT];
231
+
232
+ if (unlikely(!initialized)) {
233
+ initialized = 1;
234
+ st = rrdset_create_localhost(
235
+ "netdata", "aclk_cloud_req_cmd", NULL, "aclk", NULL, "Requests received from cloud by their type (api endpoint queried)", "req/s",
236
+ "netdata", "stats", 200007, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
237
+
238
+ for (int i = 0; i < ACLK_STATS_CLOUD_REQ_TYPE_CNT; i++)
239
+ rd_rq_types[i] = rrddim_add(st, cloud_req_type_names[i], NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
240
+ } else
241
+ rrdset_next(st);
242
+
243
+ for (int i = 0; i < ACLK_STATS_CLOUD_REQ_TYPE_CNT; i++)
244
+ rrddim_set_by_pointer(st, rd_rq_types[i], per_sample->cloud_req_by_type[i]);
245
+
246
+ rrdset_done(st);
247
+}
248
+
249
#define MAX_DIM_NAME 16
250
static void aclk_stats_query_threads(uint32_t *queries_per_thread)
251
{
@@ -191,7 +256,7 @@ static void aclk_stats_query_threads(uint32_t *queries_per_thread)
256
if (unlikely(!st)) {
257
st = rrdset_create_localhost(
258
"netdata", "aclk_query_threads", NULL, "aclk", NULL, "Queries Processed Per Thread", "req/s",
194
- "netdata", "stats", 200007, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
259
+ "netdata", "stats", 200008, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
260
261
for (int i = 0; i < query_thread_count; i++) {
262
if (snprintf(dim_name, MAX_DIM_NAME, "Query %d", i) < 0)
@@ -244,7 +309,7 @@ static void aclk_stats_cpu_threads(void)
309
310
aclk_cpu_data[i].st = rrdset_create_localhost(
311
"netdata", id, NULL, "aclk", NULL, title, "milliseconds/s",
247
- "netdata", "stats", 200008 + i, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
312
+ "netdata", "stats", 200020 + i, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
313
314
aclk_cpu_data[i].user = rrddim_add(aclk_cpu_data[i].st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
315
aclk_cpu_data[i].system = rrddim_add(aclk_cpu_data[i].st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
@@ -317,6 +382,10 @@ void *aclk_stats_main_thread(void *ptr)
382
aclk_stats_read_q(&per_sample);
383
384
aclk_stats_cloud_req(&per_sample);
385
+ aclk_stats_cloud_req_version(&per_sample);
386
+
387
+ aclk_stats_cloud_req_cmd(&per_sample);
388
+
389
aclk_stats_query_threads(aclk_queries_per_thread_sample);
390
391
aclk_stats_cpu_threads();
aclk/legacy/aclk_stats.h
+11
-1
@@ -55,6 +55,11 @@ extern struct aclk_mat_metrics {
55
56
void aclk_metric_mat_update(struct aclk_metric_mat_data *metric, usec_t measurement);
57
58
+#define ACLK_STATS_CLOUD_REQ_TYPE_CNT 7
59
+// if you change update cloud_req_type_names
60
+
61
+int aclk_cloud_req_type_to_idx(const char *name);
62
+
63
// reset to 0 on every sample
64
extern struct aclk_metrics_per_sample {
65
/* in the unlikely event of ACLK disconnecting
@@ -72,9 +77,14 @@ extern struct aclk_metrics_per_sample {
77
volatile uint32_t read_q_added;
78
volatile uint32_t read_q_consumed;
79
75
- volatile uint32_t cloud_req_recvd;
80
+ volatile uint32_t cloud_req_ok;
81
volatile uint32_t cloud_req_err;
82
83
+ volatile uint16_t cloud_req_v1;
84
+ volatile uint16_t cloud_req_v2;
85
+
86
+ volatile uint16_t cloud_req_by_type[ACLK_STATS_CLOUD_REQ_TYPE_CNT];
87
+
88
#ifdef NETDATA_INTERNAL_CHECKS
89
struct aclk_metric_mat_data latency;
90
#endif