Add ACLK-NG cloud request type charts (#11326)
- `netdata.aclk_cloud_req_http_type` will show a breakdown of HTTP query types, e.g. `/api/v1/data` vs. `/api/v1/chart` etc. - `netdata.aclk_cloud_req_type` will show a breakdown at a higher-level, e.g. `http` vs `alarm_update` vs `metadata_alarms` etc. This is based off of the entries found in `aclk/aclk_query.c#aclk_query_handlers`.
Uman Shahzad committed
Jul 19, 2021 at 13:12 UTC
c715423dc73a5f1452b7e5b126180c1335fdefc2
4 files changed
+145
-2
aclk/aclk_query.c
+7
@@ -125,6 +125,13 @@ static int http_api_v2(struct aclk_query_thread *query_thr, aclk_query_t query)
125
126
mysep = strrchr(query->data.http_api_v2.query, '/');
127
128
+ if (aclk_stats_enabled) {
129
+ ACLK_STATS_LOCK;
130
+ int stat_idx = aclk_cloud_req_http_type_to_idx(mysep ? mysep + 1 : "other");
131
+ aclk_metrics_per_sample.cloud_req_http_by_type[stat_idx]++;
132
+ ACLK_STATS_UNLOCK;
133
+ }
134
+
135
// execute the query
136
w->tv_in = query->created_tv;
137
now_realtime_timeval(&w->tv_ready);
aclk/aclk_query_queue.c
+35
@@ -45,14 +45,49 @@ static inline int _aclk_queue_query(aclk_query_t query)
45
46
}
47
48
+// Gets a pointer to the metric associated with a particular query type.
49
+// NULL if the query type has no associated metric.
50
+static inline volatile uint32_t *aclk_stats_qmetric_for_qtype(aclk_query_type_t qtype) {
51
+ switch (qtype) {
52
+ case HTTP_API_V2:
53
+ return &aclk_metrics_per_sample.cloud_req_type_http;
54
+ case ALARM_STATE_UPDATE:
55
+ return &aclk_metrics_per_sample.cloud_req_type_alarm_upd;
56
+ case METADATA_INFO:
57
+ return &aclk_metrics_per_sample.cloud_req_type_metadata_info;
58
+ case METADATA_ALARMS:
59
+ return &aclk_metrics_per_sample.cloud_req_type_metadata_alarms;
60
+ case CHART_NEW:
61
+ return &aclk_metrics_per_sample.cloud_req_type_chart_new;
62
+ case CHART_DEL:
63
+ return &aclk_metrics_per_sample.cloud_req_type_chart_del;
64
+ case REGISTER_NODE:
65
+ return &aclk_metrics_per_sample.cloud_req_type_register_node;
66
+ case NODE_STATE_UPDATE:
67
+ return &aclk_metrics_per_sample.cloud_req_type_node_upd;
68
+ default:
69
+ return NULL;
70
+ }
71
+}
72
+
73
int aclk_queue_query(aclk_query_t query)
74
{
75
int ret = _aclk_queue_query(query);
76
if (!ret) {
77
+ // local cache of query type before we wake up query thread, which may
78
+ // free the query in a race.
79
+ aclk_query_type_t qtype = query->type;
80
QUERY_THREAD_WAKEUP;
81
+
82
if (aclk_stats_enabled) {
83
+ // get target query type metric before lock so we keep lock for
84
+ // minimal time.
85
+ volatile uint32_t *metric = aclk_stats_qmetric_for_qtype(qtype);
86
+
87
ACLK_STATS_LOCK;
88
aclk_metrics_per_sample.queries_queued++;
89
+ if (metric)
90
+ *metric += 1;
91
ACLK_STATS_UNLOCK;
92
}
93
}
aclk/aclk_stats.c
+85
-2
@@ -110,6 +110,86 @@ static void aclk_stats_cloud_req(struct aclk_metrics_per_sample *per_sample)
110
rrdset_done(st);
111
}
112
113
+static void aclk_stats_cloud_req_type(struct aclk_metrics_per_sample *per_sample)
114
+{
115
+ static RRDSET *st = NULL;
116
+ static RRDDIM *rd_type_http = NULL;
117
+ static RRDDIM *rd_type_alarm_upd = NULL;
118
+ static RRDDIM *rd_type_metadata_info = NULL;
119
+ static RRDDIM *rd_type_metadata_alarms = NULL;
120
+ static RRDDIM *rd_type_chart_new = NULL;
121
+ static RRDDIM *rd_type_chart_del = NULL;
122
+ static RRDDIM *rd_type_register_node = NULL;
123
+ static RRDDIM *rd_type_node_upd = NULL;
124
+
125
+ if (unlikely(!st)) {
126
+ st = rrdset_create_localhost(
127
+ "netdata", "aclk_cloud_req_type", NULL, "aclk", NULL, "Requests received from cloud by their type", "req/s",
128
+ "netdata", "stats", 200006, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
129
+
130
+ rd_type_http = rrddim_add(st, "http", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
131
+ rd_type_alarm_upd = rrddim_add(st, "alarm update", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
132
+ rd_type_metadata_info = rrddim_add(st, "info metadata", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
133
+ rd_type_metadata_alarms = rrddim_add(st, "alarms metadata", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
134
+ rd_type_chart_new = rrddim_add(st, "chart new", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
135
+ rd_type_chart_del = rrddim_add(st, "chart delete", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
136
+ rd_type_register_node = rrddim_add(st, "register node", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
137
+ rd_type_node_upd = rrddim_add(st, "node update", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
138
+ } else
139
+ rrdset_next(st);
140
+
141
+ rrddim_set_by_pointer(st, rd_type_http, per_sample->cloud_req_type_http);
142
+ rrddim_set_by_pointer(st, rd_type_alarm_upd, per_sample->cloud_req_type_alarm_upd);
143
+ rrddim_set_by_pointer(st, rd_type_metadata_info, per_sample->cloud_req_type_metadata_info);
144
+ rrddim_set_by_pointer(st, rd_type_metadata_alarms, per_sample->cloud_req_type_metadata_alarms);
145
+ rrddim_set_by_pointer(st, rd_type_chart_new, per_sample->cloud_req_type_chart_new);
146
+ rrddim_set_by_pointer(st, rd_type_chart_del, per_sample->cloud_req_type_chart_del);
147
+ rrddim_set_by_pointer(st, rd_type_register_node, per_sample->cloud_req_type_register_node);
148
+ rrddim_set_by_pointer(st, rd_type_node_upd, per_sample->cloud_req_type_node_upd);
149
+
150
+ rrdset_done(st);
151
+}
152
+
153
+static char *cloud_req_http_type_names[ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT] = {
154
+ "other",
155
+ "info",
156
+ "data",
157
+ "alarms",
158
+ "alarm_log",
159
+ "chart",
160
+ "charts"
161
+ // if you change then update `ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT`.
162
+};
163
+
164
+int aclk_cloud_req_http_type_to_idx(const char *name)
165
+{
166
+ for (int i = 1; i < ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT; i++)
167
+ if (!strcmp(cloud_req_http_type_names[i], name))
168
+ return i;
169
+ return 0;
170
+}
171
+
172
+static void aclk_stats_cloud_req_http_type(struct aclk_metrics_per_sample *per_sample)
173
+{
174
+ static RRDSET *st = NULL;
175
+ static RRDDIM *rd_rq_types[ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT];
176
+
177
+ if (unlikely(!st)) {
178
+ st = rrdset_create_localhost(
179
+ "netdata", "aclk_cloud_req_http_type", NULL, "aclk", NULL, "Requests received from cloud via HTTP by their type", "req/s",
180
+ "netdata", "stats", 200007, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
181
+
182
+ for (int i = 0; i < ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT; i++)
183
+ rd_rq_types[i] = rrddim_add(st, cloud_req_http_type_names[i], NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
184
+ } else
185
+ rrdset_next(st);
186
+
187
+ for (int i = 0; i < ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT; i++)
188
+ rrddim_set_by_pointer(st, rd_rq_types[i], per_sample->cloud_req_http_by_type[i]);
189
+
190
+ rrdset_done(st);
191
+}
192
+
193
#define MAX_DIM_NAME 16
194
static void aclk_stats_query_threads(uint32_t *queries_per_thread)
195
{
@@ -120,7 +200,7 @@ static void aclk_stats_query_threads(uint32_t *queries_per_thread)
200
if (unlikely(!st)) {
201
st = rrdset_create_localhost(
202
"netdata", "aclk_query_threads", NULL, "aclk", NULL, "Queries Processed Per Thread", "req/s",
123
- "netdata", "stats", 200007, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
203
+ "netdata", "stats", 200009, localhost->rrd_update_every, RRDSET_TYPE_STACKED);
204
205
for (int i = 0; i < query_thread_count; i++) {
206
if (snprintf(dim_name, MAX_DIM_NAME, "Query %d", i) < 0)
@@ -147,7 +227,7 @@ static void aclk_stats_query_time(struct aclk_metrics_per_sample *per_sample)
227
if (unlikely(!st)) {
228
st = rrdset_create_localhost(
229
"netdata", "aclk_query_time", NULL, "aclk", NULL, "Time it took to process cloud requested DB queries", "us",
150
- "netdata", "stats", 200006, localhost->rrd_update_every, RRDSET_TYPE_LINE);
230
+ "netdata", "stats", 200008, localhost->rrd_update_every, RRDSET_TYPE_LINE);
231
232
rd_rq_avg = rrddim_add(st, "avg", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
233
rd_rq_max = rrddim_add(st, "max", NULL, 1, localhost->rrd_update_every, RRD_ALGORITHM_ABSOLUTE);
@@ -216,6 +296,9 @@ void *aclk_stats_main_thread(void *ptr)
296
#endif
297
298
aclk_stats_cloud_req(&per_sample);
299
+ aclk_stats_cloud_req_type(&per_sample);
300
+ aclk_stats_cloud_req_http_type(&per_sample);
301
+
302
aclk_stats_query_threads(aclk_queries_per_thread_sample);
303
304
aclk_stats_query_time(&per_sample);
aclk/aclk_stats.h
+18
@@ -13,6 +13,11 @@ extern netdata_mutex_t aclk_stats_mutex;
13
#define ACLK_STATS_LOCK netdata_mutex_lock(&aclk_stats_mutex)
14
#define ACLK_STATS_UNLOCK netdata_mutex_unlock(&aclk_stats_mutex)
15
16
+// if you change update `cloud_req_http_type_names`.
17
+#define ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT 7
18
+
19
+int aclk_cloud_req_http_type_to_idx(const char *name);
20
+
21
struct aclk_stats_thread {
22
netdata_thread_t *thread;
23
int query_thread_count;
@@ -43,6 +48,19 @@ extern struct aclk_metrics_per_sample {
48
volatile uint32_t cloud_req_recvd;
49
volatile uint32_t cloud_req_err;
50
51
+ // request types.
52
+ volatile uint32_t cloud_req_type_http;
53
+ volatile uint32_t cloud_req_type_alarm_upd;
54
+ volatile uint32_t cloud_req_type_metadata_info;
55
+ volatile uint32_t cloud_req_type_metadata_alarms;
56
+ volatile uint32_t cloud_req_type_chart_new;
57
+ volatile uint32_t cloud_req_type_chart_del;
58
+ volatile uint32_t cloud_req_type_register_node;
59
+ volatile uint32_t cloud_req_type_node_upd;
60
+
61
+ // HTTP-specific request types.
62
+ volatile uint32_t cloud_req_http_by_type[ACLK_STATS_CLOUD_HTTP_REQ_TYPE_CNT];
63
+
64
volatile uint32_t cloud_q_process_total;
65
volatile uint32_t cloud_q_process_count;
66
volatile uint32_t cloud_q_process_max;