@cryptotaxi247 / netdata-1 / commits / 6c41244db

add more aclk worker jobs (#19435)

* add more aclk worker jobs * garbage collect aclk buffer, when receiving ackowledgements * add msg callback worker job * added latency histogram for aclk pub-ack * fix compilation * Add a few workers, handle context checkpoint async * Proper register worker --------- Co-authored-by: Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com>

Costa Tsaousis committed Jan 18, 2025 at 21:14 UTC 6c41244db9557c96b4813a28c21fcd4e2a044127
12 files changed +366 -29
src/aclk/aclk.c
+11
@@ -799,6 +799,17 @@ void *aclk_main(void *ptr)
799 worker_register_job_name(WORKER_ACLK_HANDLE_MQTT_INTERNAL, "mqtt internal");
800 worker_register_job_name(WORKER_ACLK_TX, "tx");
801 worker_register_job_name(WORKER_ACLK_TX_ERROR, "tx error");
802 + worker_register_job_name(WORKER_ACLK_TRY_SEND_ALL, "try send all");
803 + worker_register_job_name(WORKER_ACLK_HANDLE_INCOMING, "handle incoming");
804 + worker_register_job_name(WORKER_ACLK_CPT_CONNACK, "cpt connack");
805 + worker_register_job_name(WORKER_ACLK_CPT_PUBACK, "cpt puback");
806 + worker_register_job_name(WORKER_ACLK_CPT_PINGRESP, "cpt pingresp");
807 + worker_register_job_name(WORKER_ACLK_CPT_SUBACK, "cpt suback");
808 + worker_register_job_name(WORKER_ACLK_CPT_PUBLISH, "cpt publish");
809 + worker_register_job_name(WORKER_ACLK_CPT_DISCONNECT, "cpt disconnect");
810 + worker_register_job_name(WORKER_ACLK_CPT_UNKNOWN, "cpt unknown");
811 + worker_register_job_name(WORKER_ACLK_SEND_FRAGMENT, "send fragment");
812 + worker_register_job_name(WORKER_ACLK_MSG_CALLBACK, "msg callback");
813
814 ACLK_PROXY_TYPE proxy_type;
815 aclk_get_proxy(&proxy_type);
src/aclk/aclk_contexts_api.c
+2 -2
@@ -6,7 +6,7 @@
6
7 void aclk_send_contexts_snapshot(contexts_snapshot_t data)
8 {
9 - aclk_query_t query = aclk_query_new(PROTO_BIN_MESSAGE);
9 + aclk_query_t query = aclk_query_new(CTX_SEND_SNAPSHOT);
10 query->data.bin_payload.topic = ACLK_TOPICID_CTXS_SNAPSHOT;
11 query->data.bin_payload.payload = contexts_snapshot_2bin(data, &query->data.bin_payload.size);
12 query->data.bin_payload.msg_name = "ContextsSnapshot";
@@ -15,7 +15,7 @@ void aclk_send_contexts_snapshot(contexts_snapshot_t data)
15
16 void aclk_send_contexts_updated(contexts_updated_t data)
17 {
18 - aclk_query_t query = aclk_query_new(PROTO_BIN_MESSAGE);
18 + aclk_query_t query = aclk_query_new(CTX_SEND_SNAPSHOT_UPD);
19 query->data.bin_payload.topic = ACLK_TOPICID_CTXS_UPDATED;
20 query->data.bin_payload.payload = contexts_updated_2bin(data, &query->data.bin_payload.size);
21 query->data.bin_payload.msg_name = "ContextsUpdated";
src/aclk/aclk_query_queue.h
+7 -2
@@ -18,8 +18,12 @@ typedef enum {
18 ALARM_PROVIDE_CFG,
19 ALARM_SNAPSHOT,
20 UPDATE_NODE_COLLECTORS,
21 - PROTO_BIN_MESSAGE,
22 - ACLK_QUERY_TYPE_COUNT // always keep this as last
21 + CTX_SEND_SNAPSHOT, // Context snapshot to the cloud
22 + CTX_SEND_SNAPSHOT_UPD, // Context incremental update to the cloud
23 + CTX_CHECKPOINT, // Context checkpoint from the cloud
24 + CTX_STOP_STREAMING, // Context stop streaming
25 + CREATE_NODE_INSTANCE, // Create node instance on the agent
26 + ACLK_QUERY_TYPE_COUNT // always keep this as last
27 } aclk_query_type_t;
28
29 struct aclk_query_http_api_v2 {
@@ -56,6 +60,7 @@ struct aclk_query {
60 union {
61 struct aclk_query_http_api_v2 http_api_v2;
62 struct aclk_bin_payload bin_payload;
63 + void *payload;
64 } data;
65 };
66
src/aclk/aclk_rx_msgs.c
+7 -10
@@ -6,6 +6,7 @@
6 #include "aclk.h"
7 #include "aclk_capas.h"
8 #include "aclk_query.h"
9 +#include "mqtt_websockets/aclk_mqtt_workers.h"
10
11 #include "schema-wrappers/proto_2_json.h"
12
@@ -417,11 +418,9 @@ int contexts_checkpoint(const char *msg, size_t msg_len)
418 if (!cmd)
419 return 1;
420
420 - rrdcontext_hub_checkpoint_command(cmd);
421 -
422 - freez(cmd->claim_id);
423 - freez(cmd->node_id);
424 - freez(cmd);
421 + aclk_query_t query = aclk_query_new(CTX_CHECKPOINT);
422 + query->data.payload = cmd;
423 + aclk_execute_query(query);
424 return 0;
425 }
426
@@ -436,11 +435,9 @@ int stop_streaming_contexts(const char *msg, size_t msg_len)
435 if (!cmd)
436 return 1;
437
439 - rrdcontext_hub_stop_streaming_command(cmd);
440 -
441 - freez(cmd->claim_id);
442 - freez(cmd->node_id);
443 - freez(cmd);
438 + aclk_query_t query = aclk_query_new(CTX_STOP_STREAMING);
439 + query->data.payload = cmd;
440 + aclk_execute_query(query);
441 return 0;
442 }
443
src/aclk/mqtt_websockets/aclk_mqtt_workers.h
+11
@@ -26,5 +26,16 @@
26 #define WORKER_ACLK_HANDLE_MQTT_INTERNAL 20
27 #define WORKER_ACLK_TX 21
28 #define WORKER_ACLK_TX_ERROR 22
29 +#define WORKER_ACLK_TRY_SEND_ALL 23
30 +#define WORKER_ACLK_HANDLE_INCOMING 24
31 +#define WORKER_ACLK_CPT_CONNACK 25
32 +#define WORKER_ACLK_CPT_PUBACK 26
33 +#define WORKER_ACLK_CPT_PINGRESP 27
34 +#define WORKER_ACLK_CPT_SUBACK 28
35 +#define WORKER_ACLK_CPT_PUBLISH 29
36 +#define WORKER_ACLK_CPT_DISCONNECT 30
37 +#define WORKER_ACLK_CPT_UNKNOWN 31
38 +#define WORKER_ACLK_SEND_FRAGMENT 32
39 +#define WORKER_ACLK_MSG_CALLBACK 33
40
41 #endif //NETDATA_ACLK_MQTT_WORKERS_H
src/aclk/mqtt_websockets/mqtt_ng.c
+42 -6
@@ -5,10 +5,12 @@
5 #endif
6
7 #include "libnetdata/libnetdata.h"
8 +void pulse_aclk_sent_message_acked(usec_t usec, size_t len);
9
10 #include "common_internal.h"
11 #include "mqtt_constants.h"
12 #include "mqtt_ng.h"
13 +#include "aclk_mqtt_workers.h"
14
15 #define SMALL_STRING_DONT_FRAGMENT_LIMIT 128
16
@@ -31,14 +33,13 @@
33
34 typedef uint16_t buffer_frag_flag_t;
35 struct buffer_fragment {
34 - size_t len;
35 - size_t sent;
36 + uint32_t len;
37 + uint32_t sent;
38 buffer_frag_flag_t flags;
39 + uint16_t packet_id;
40 void (*free_fnc)(void *ptr);
41 unsigned char *data;
39 -
40 - uint16_t packet_id;
41 -
42 + usec_t sent_monotonic_ut;
43 struct buffer_fragment *next;
44 };
45
@@ -1851,6 +1852,7 @@ static int mqtt_ng_next_to_send(struct mqtt_ng_client *client) {
1852 if ( client->ping_pending && (!frag || (frag->flags & BUFFER_FRAG_MQTT_PACKET_HEAD && frag->sent == 0)) ) {
1853 client->ping_pending = 0;
1854 ping_frag.sent = 0;
1855 + ping_frag.sent_monotonic_ut = 0;
1856 client->main_buffer.sending_frag = &ping_frag;
1857 return 0;
1858 }
@@ -1865,6 +1867,8 @@ static int mqtt_ng_next_to_send(struct mqtt_ng_client *client) {
1867 // nothing could be written anymore
1868 // return 1 if last fragment of a message was fully sent
1869 static int send_fragment(struct mqtt_ng_client *client) {
1870 + worker_is_busy(WORKER_ACLK_SEND_FRAGMENT);
1871 +
1872 struct buffer_fragment *frag = client->main_buffer.sending_frag;
1873
1874 // for readability
@@ -1878,6 +1882,7 @@ static int send_fragment(struct mqtt_ng_client *client) {
1882 else
1883 nd_log(NDLS_DAEMON, NDLP_WARNING, "This fragment was fully sent already. This should not happen!");
1884
1885 + frag->sent_monotonic_ut = now_monotonic_usec();
1886 frag->sent += processed;
1887 if (frag->sent != frag->len)
1888 return -1;
@@ -1925,6 +1930,7 @@ static void mark_message_for_gc(struct buffer_fragment *frag)
1930
1931 static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1932 {
1933 + size_t reclaimable = 0;
1934 LOCK_HDR_BUFFER(&client->main_buffer);
1935 struct buffer_fragment *frag = BUFFER_FIRST_FRAG(&client->main_buffer.hdr_buffer);
1936 while (frag) {
@@ -1934,10 +1940,20 @@ static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1940 UNLOCK_HDR_BUFFER(&client->main_buffer);
1941 return 1;
1942 }
1943 + pulse_aclk_sent_message_acked(frag->sent_monotonic_ut, frag->len);
1944 mark_message_for_gc(frag);
1945 +
1946 + size_t used = BUFFER_BYTES_USED(&client->main_buffer.hdr_buffer);
1947 + if (reclaimable >= (used / 4))
1948 + transaction_buffer_garbage_collect(&client->main_buffer);
1949 +
1950 UNLOCK_HDR_BUFFER(&client->main_buffer);
1951 return 0;
1952 }
1953 +
1954 + if(frag_is_marked_for_gc(frag))
1955 + reclaimable += FRAG_SIZE_IN_BUFFER(frag);
1956 +
1957 frag = frag->next;
1958 }
1959 nd_log(NDLS_DAEMON, NDLP_ERR, "Received packet_id (%" PRIu16 ") is unknown!", packet_id);
@@ -1963,6 +1979,8 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
1979 uint8_t ctrl_packet_type = get_control_packet_type(client->parser.mqtt_control_packet_type);
1980 switch (ctrl_packet_type) {
1981 case MQTT_CPT_CONNACK:
1982 + worker_is_busy(WORKER_ACLK_CPT_CONNACK);
1983 +
1984 LOCK_HDR_BUFFER(&client->main_buffer);
1985 mark_message_for_gc(client->connect_msg);
1986 UNLOCK_HDR_BUFFER(&client->main_buffer);
@@ -1991,6 +2009,8 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2009 return MQTT_NG_CLIENT_SERVER_RETURNED_ERROR;
2010
2011 case MQTT_CPT_PUBACK:
2012 + worker_is_busy(WORKER_ACLK_CPT_PUBACK);
2013 +
2014 if (mark_packet_acked(client, client->parser.mqtt_packet.puback.packet_id))
2015 return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2016 if (client->puback_callback)
@@ -1998,14 +2018,18 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2018 break;
2019
2020 case MQTT_CPT_PINGRESP:
2021 + worker_is_busy(WORKER_ACLK_CPT_PINGRESP);
2022 + pulse_aclk_sent_message_acked(ping_frag.sent_monotonic_ut, ping_frag.len);
2023 break;
2024
2025 case MQTT_CPT_SUBACK:
2026 + worker_is_busy(WORKER_ACLK_CPT_SUBACK);
2027 if (mark_packet_acked(client, client->parser.mqtt_packet.suback.packet_id))
2028 return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2029 break;
2030
2031 case MQTT_CPT_PUBLISH:
2032 + worker_is_busy(WORKER_ACLK_CPT_PUBLISH);
2033 pub = &client->parser.mqtt_packet.publish;
2034
2035 if (pub->qos > 1) {
@@ -2038,8 +2062,11 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2062 }
2063 }
2064
2041 - if (client->msg_callback)
2065 + if (client->msg_callback) {
2066 + worker_is_busy(WORKER_ACLK_MSG_CALLBACK);
2067 client->msg_callback(pub->topic, pub->data, pub->data_len, pub->qos);
2068 + }
2069 +
2070 // in case we have property topic alias and we have topic we take over the string
2071 // and add pointer to it into topic alias list
2072 if (prop == NULL)
@@ -2048,11 +2075,13 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2075 return MQTT_NG_CLIENT_WANT_WRITE;
2076
2077 case MQTT_CPT_DISCONNECT:
2078 + worker_is_busy(WORKER_ACLK_CPT_DISCONNECT);
2079 nd_log(NDLS_DAEMON, NDLP_INFO, "Got MQTT DISCONNECT control packet from server. Reason code: %d", (int)client->parser.mqtt_packet.disconnect.reason_code);
2080 client->client_state = MQTT_STATE_DISCONNECTED;
2081 break;
2082
2083 default:
2084 + worker_is_busy(WORKER_ACLK_CPT_UNKNOWN);
2085 nd_log(NDLS_DAEMON, NDLP_INFO, "Got unknown control packet %u from server", ctrl_packet_type);
2086 break;
2087 }
@@ -2068,19 +2097,26 @@ int mqtt_ng_sync(struct mqtt_ng_client *client)
2097 if (client->client_state == MQTT_STATE_ERROR)
2098 return 1;
2099
2100 + worker_is_busy(WORKER_ACLK_TRY_SEND_ALL);
2101 +
2102 LOCK_HDR_BUFFER(&client->main_buffer);
2103 try_send_all(client);
2104 UNLOCK_HDR_BUFFER(&client->main_buffer);
2105
2106 int rc;
2107
2108 + worker_is_busy(WORKER_ACLK_HANDLE_INCOMING);
2109 while ((rc = handle_incoming_traffic(client)) != MQTT_NG_CLIENT_NEED_MORE_BYTES) {
2110 if (rc < 0)
2111 break;
2112 if (rc == MQTT_NG_CLIENT_WANT_WRITE) {
2113 + worker_is_busy(WORKER_ACLK_TRY_SEND_ALL);
2114 +
2115 LOCK_HDR_BUFFER(&client->main_buffer);
2116 try_send_all(client);
2117 UNLOCK_HDR_BUFFER(&client->main_buffer);
2118 +
2119 + worker_is_busy(WORKER_ACLK_HANDLE_INCOMING);
2120 }
2121 }
2122
src/daemon/libuv_workers.c
+11
@@ -60,6 +60,17 @@ void register_libuv_worker_jobs() {
60 worker_register_job_name(UV_EVENT_ACLK_NODE_INFO, "aclk host node info");
61 worker_register_job_name(UV_EVENT_ACLK_ALERT_PUSH, "aclk alert push");
62 worker_register_job_name(UV_EVENT_ACLK_QUERY_EXECUTE, "aclk query execute");
63 + // aclk
64 + worker_register_job_name(UV_EVENT_CTX_STOP_STREAMING, "ctx stop streaming");
65 + worker_register_job_name(UV_EVENT_CTX_CHECKPOINT, "ctx version check");
66 + worker_register_job_name(UV_EVENT_ALARM_PROVIDE_CFG, "send alarm config");
67 + worker_register_job_name(UV_EVENT_ALARM_SNAPSHOT, "alert snapshot");
68 + worker_register_job_name(UV_EVENT_REGISTER_NODE, "register node");
69 + worker_register_job_name(UV_EVENT_UPDATE_NODE_COLLECTORS, "update collectors");
70 + worker_register_job_name(UV_EVENT_UPDATE_NODE_INFO, "send node info");
71 + worker_register_job_name(UV_EVENT_CTX_SEND_SNAPSHOT, "ctx send snapshot");
72 + worker_register_job_name(UV_EVENT_CTX_SEND_SNAPSHOT_UPD, "ctx send update");
73 + worker_register_job_name(UV_EVENT_NODE_STATE_UPDATE, "node state update");
74
75 // netdatacli
76 worker_register_job_name(UV_EVENT_SCHEDULE_CMD, "schedule command");
src/daemon/libuv_workers.h
+12
@@ -53,6 +53,18 @@ enum event_loop_job {
53 UV_EVENT_ACLK_ALERT_PUSH,
54 UV_EVENT_ACLK_QUERY_EXECUTE,
55
56 + //
57 + UV_EVENT_CTX_STOP_STREAMING,
58 + UV_EVENT_CTX_CHECKPOINT,
59 + UV_EVENT_ALARM_PROVIDE_CFG,
60 + UV_EVENT_ALARM_SNAPSHOT,
61 + UV_EVENT_REGISTER_NODE,
62 + UV_EVENT_UPDATE_NODE_COLLECTORS,
63 + UV_EVENT_UPDATE_NODE_INFO,
64 + UV_EVENT_CTX_SEND_SNAPSHOT,
65 + UV_EVENT_CTX_SEND_SNAPSHOT_UPD,
66 + UV_EVENT_NODE_STATE_UPDATE,
67 +
68 // netdatacli
69 UV_EVENT_SCHEDULE_CMD,
70 };
src/daemon/pulse/pulse-network.c
+184
@@ -19,6 +19,130 @@ static struct network_statistics {
19 PAD64(uint64_t) stream_bytes_sent;
20 } live_stats = { 0 };
21
22 +// --------------------------------------------------------------------------------------------------------------------
23 +// aclk time heatmap
24 +// a similar history exists in dbengine cache.c
25 +
26 +struct aclk_histogram_entry {
27 + usec_t upto;
28 + size_t count;
29 +};
30 +
31 +#define ACLK_TIME_HISTOGRAM_ENTRIES 19
32 +
33 +static struct aclk_time_histogram {
34 + struct aclk_histogram_entry array[ACLK_TIME_HISTOGRAM_ENTRIES];
35 +} aclk_time_heatmap;
36 +
37 +void aclk_time_histogram_init(void) {
38 + struct aclk_time_histogram *h = &aclk_time_heatmap;
39 +
40 + // the histogram MUST be all-inclusive for the possible sizes,
41 + // so we start from 0, and the last value is UINT64_MAX.
42 +
43 + usec_t values[ACLK_TIME_HISTOGRAM_ENTRIES] = {
44 + // minimum
45 + 0,
46 +
47 + // ms
48 + 10 * USEC_PER_MS,
49 + 50 * USEC_PER_MS, 100 * USEC_PER_MS, 200 * USEC_PER_MS, 350 * USEC_PER_MS,
50 + 500 * USEC_PER_MS, 750 * USEC_PER_MS,
51 +
52 + // seconds
53 + 1 * USEC_PER_SEC, 2 * USEC_PER_SEC, 4 * USEC_PER_SEC, 8 * USEC_PER_SEC,
54 + 15 * USEC_PER_SEC, 30 * USEC_PER_SEC, 45 * USEC_PER_SEC,
55 +
56 + // minutes
57 + 60 * USEC_PER_SEC, 120 * USEC_PER_SEC, 180 * USEC_PER_SEC,
58 +
59 + // maximum
60 + UINT64_MAX
61 + };
62 +
63 + usec_t last_value = 0;
64 + for(size_t i = 0; i < ACLK_TIME_HISTOGRAM_ENTRIES; i++) {
65 + if(i > 0 && values[i] == 0)
66 + fatal("only the first value in the array can be zero");
67 +
68 + if(i > 0 && values[i] <= last_value)
69 + fatal("the values need to be sorted");
70 +
71 + h->array[i].upto = values[i];
72 + last_value = values[i];
73 + }
74 +}
75 +
76 +static inline size_t aclk_time_histogram_slot(struct aclk_time_histogram *h, usec_t dt_ut) {
77 + if(dt_ut <= h->array[0].upto)
78 + return 0;
79 +
80 + if(dt_ut >= h->array[_countof(h->array) - 1].upto)
81 + return _countof(h->array) - 1;
82 +
83 + // binary search for the right size
84 + size_t low = 0, high = _countof(h->array) - 1;
85 + while (low < high) {
86 + size_t mid = low + (high - low) / 2;
87 + if (dt_ut < h->array[mid].upto)
88 + high = mid;
89 + else
90 + low = mid + 1;
91 + }
92 + return low - 1;
93 +}
94 +
95 +void pulse_aclk_sent_message_acked(usec_t sent_ut, size_t len __maybe_unused) {
96 + if(!sent_ut) return;
97 +
98 + usec_t usec = now_monotonic_usec() - sent_ut;
99 +
100 + size_t slot = aclk_time_histogram_slot(&aclk_time_heatmap, usec);
101 + internal_fatal(slot >= _countof(aclk_time_heatmap.array), "hey!");
102 +
103 + __atomic_add_fetch(&aclk_time_heatmap.array[slot].count, 1, __ATOMIC_RELAXED);
104 +}
105 +
106 +static void pulse_aclk_time_heatmap(void) {
107 + static RRDSET *st;
108 + static RRDDIM *rds[ACLK_TIME_HISTOGRAM_ENTRIES];
109 +
110 + if(!st) {
111 + st = rrdset_create_localhost(
112 + "netdata",
113 + "aclk_puback_latency",
114 + NULL,
115 + PULSE_NETWORK_CHART_FAMILY,
116 + "netdata.aclk_puback_latency",
117 + "Netdata ACLK PubACK Latency In Seconds",
118 + "messages",
119 + "netdata",
120 + "pulse",
121 + PULSE_NETWORK_CHART_PRIORITY + 1,
122 + localhost->rrd_update_every,
123 + RRDSET_TYPE_HEATMAP);
124 +
125 + rds[0] = rrddim_add(st, "instant", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
126 + for(size_t i = 1; i < _countof(rds) - 1 ;i++) {
127 + char buf[128];
128 + snprintf(buf, sizeof(buf), "%.2fs", (double)aclk_time_heatmap.array[i].upto / (double)USEC_PER_SEC);
129 + // duration_snprintf(buf, sizeof(buf), aclk_time_heatmap.array[i].upto, "us", false);
130 + rds[i] = rrddim_add(st, buf, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
131 + }
132 + rds[_countof(rds) - 1] = rrddim_add(st, "+inf", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
133 + }
134 +
135 + for(size_t i = 0; i < _countof(rds) - 1 ;i++) {
136 + size_t old_value = 0, new_value = 0;
137 + __atomic_exchange(&aclk_time_heatmap.array[i].count, &new_value, &old_value, __ATOMIC_RELAXED);
138 + rrddim_set_by_pointer(st, rds[i], (collected_number)old_value);
139 + }
140 +
141 + rrdset_done(st);
142 +}
143 +
144 +// --------------------------------------------------------------------------------------------------------------------
145 +
146 void pulse_web_server_received_bytes(size_t bytes) {
147 __atomic_add_fetch(&live_stats.api_bytes_received, bytes, __ATOMIC_RELAXED);
148 }
@@ -185,5 +309,65 @@ void pulse_network_do(bool extended __maybe_unused) {
309 rrddim_set_by_pointer(st_bytes, rd_out, (collected_number)t.bytes_tx);
310 rrdset_done(st_bytes);
311 }
312 +
313 + pulse_aclk_time_heatmap();
314 +
315 + if(extended) {
316 + static RRDSET *st_aclk_queue_size = NULL;
317 + static RRDDIM *rd_messages = NULL;
318 +
319 + if (unlikely(!st_aclk_queue_size)) {
320 + st_aclk_queue_size = rrdset_create_localhost(
321 + "netdata",
322 + "network_aclk_send_queue",
323 + NULL,
324 + PULSE_NETWORK_CHART_FAMILY,
325 + "netdata.network_aclk_send_queue",
326 + "Netdata ACLK Send Queue Size",
327 + "messages",
328 + "netdata",
329 + "pulse",
330 + PULSE_NETWORK_CHART_PRIORITY + 2,
331 + localhost->rrd_update_every,
332 + RRDSET_TYPE_AREA);
333 +
334 + rrdlabels_add(st_aclk_queue_size->rrdlabels, "endpoint", "aclk", RRDLABEL_SRC_AUTO);
335 +
336 + rd_messages = rrddim_add(st_aclk_queue_size, "messages", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
337 + }
338 +
339 + rrddim_set_by_pointer(st_aclk_queue_size, rd_messages, (collected_number)t.mqtt.tx_messages_queued);
340 + rrdset_done(st_aclk_queue_size);
341 + }
342 +
343 + if(extended) {
344 + static RRDSET *st_aclk_messages = NULL;
345 + static RRDDIM *rd_in = NULL, *rd_out = NULL;
346 +
347 + if (unlikely(!st_aclk_messages)) {
348 + st_aclk_messages = rrdset_create_localhost(
349 + "netdata",
350 + "network_aclk_messages",
351 + NULL,
352 + PULSE_NETWORK_CHART_FAMILY,
353 + "netdata.network_aclk_messages",
354 + "Netdata ACLK Messages",
355 + "messages/s",
356 + "netdata",
357 + "pulse",
358 + PULSE_NETWORK_CHART_PRIORITY + 3,
359 + localhost->rrd_update_every,
360 + RRDSET_TYPE_AREA);
361 +
362 + rrdlabels_add(st_aclk_messages->rrdlabels, "endpoint", "aclk", RRDLABEL_SRC_AUTO);
363 +
364 + rd_in = rrddim_add(st_aclk_messages, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
365 + rd_out = rrddim_add(st_aclk_messages, "queued", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
366 + }
367 +
368 + rrddim_set_by_pointer(st_aclk_messages, rd_in, (collected_number)t.mqtt.rx_messages_rcvd);
369 + rrddim_set_by_pointer(st_aclk_messages, rd_out, (collected_number)t.mqtt.tx_messages_sent);
370 + rrdset_done(st_aclk_messages);
371 + }
372 }
373 }
src/daemon/pulse/pulse-network.h
+6
@@ -16,4 +16,10 @@ void pulse_statsd_sent_bytes(size_t bytes);
16 void pulse_stream_received_bytes(size_t bytes);
17 void pulse_stream_sent_bytes(size_t bytes);
18
19 +void pulse_aclk_sent_message_acked(usec_t usec, size_t len);
20 +
21 +#ifdef PULSE_INTERNALS
22 +void aclk_time_histogram_init(void);
23 +#endif
24 +
25 #endif //NETDATA_PULSE_NETWORK_H
src/daemon/pulse/pulse.c
+1
@@ -73,6 +73,7 @@ void *pulse_thread_main(void *ptr) {
73 }
74
75 pulse_aral_init();
76 + aclk_time_histogram_init();
77
78 usec_t step = update_every * USEC_PER_SEC;
79 heartbeat_t hb;
src/database/sqlite/sqlite_aclk.c
+72 -9
@@ -303,18 +303,83 @@ static void after_aclk_run_query_job(uv_work_t *req, int status __maybe_unused)
303 freez(payload);
304 }
305
306 -static void aclk_run_query(struct aclk_sync_config_s *config, aclk_query_t query)
306 +static void aclk_run_query(struct aclk_sync_config_s *config, aclk_query_t query, bool is_worker)
307 {
308 if (query->type == UNKNOWN || query->type >= ACLK_QUERY_TYPE_COUNT) {
309 error_report("Unknown query in query queue. %u", query->type);
310 return;
311 }
312
313 - if (query->type == HTTP_API_V2) {
314 - http_api_v2(config->client, query);
315 - } else {
316 - send_bin_msg(config->client, query);
313 + struct ctxs_checkpoint *cmd;
314 +
315 + bool ok_to_send = true;
316 +
317 + switch (query->type) {
318 + case HTTP_API_V2:
319 + if (is_worker)
320 + worker_is_busy(UV_EVENT_ACLK_QUERY_EXECUTE);
321 + http_api_v2(config->client, query);
322 + ok_to_send = false;
323 + break;
324 + case CTX_CHECKPOINT:;
325 + if (is_worker)
326 + worker_is_busy(UV_EVENT_CTX_CHECKPOINT);
327 + cmd = query->data.payload;
328 + rrdcontext_hub_checkpoint_command(cmd);
329 + freez(cmd->claim_id);
330 + freez(cmd->node_id);
331 + freez(cmd);
332 + ok_to_send = false;
333 + break;
334 + case CTX_STOP_STREAMING:
335 + if (is_worker)
336 + worker_is_busy(UV_EVENT_CTX_STOP_STREAMING);
337 + cmd = query->data.payload;
338 + rrdcontext_hub_stop_streaming_command(cmd);
339 + freez(cmd->claim_id);
340 + freez(cmd->node_id);
341 + freez(cmd);
342 + ok_to_send = false;
343 + break;
344 + case ALARM_PROVIDE_CFG:
345 + if (is_worker)
346 + worker_is_busy(UV_EVENT_ALARM_PROVIDE_CFG);
347 + break;
348 + case ALARM_SNAPSHOT:
349 + if (is_worker)
350 + worker_is_busy(UV_EVENT_ALARM_SNAPSHOT);
351 + break;
352 + case REGISTER_NODE:
353 + if (is_worker)
354 + worker_is_busy(UV_EVENT_REGISTER_NODE);
355 + break;
356 + case UPDATE_NODE_COLLECTORS:
357 + if (is_worker)
358 + worker_is_busy(UV_EVENT_UPDATE_NODE_COLLECTORS);
359 + break;
360 + case UPDATE_NODE_INFO:
361 + if (is_worker)
362 + worker_is_busy(UV_EVENT_UPDATE_NODE_INFO);
363 + break;
364 + case CTX_SEND_SNAPSHOT:
365 + if (is_worker)
366 + worker_is_busy(UV_EVENT_CTX_SEND_SNAPSHOT);
367 + break;
368 + case CTX_SEND_SNAPSHOT_UPD:
369 + if (is_worker)
370 + worker_is_busy(UV_EVENT_CTX_SEND_SNAPSHOT_UPD);
371 + break;
372 + case NODE_STATE_UPDATE:
373 + if (is_worker)
374 + worker_is_busy(UV_EVENT_NODE_STATE_UPDATE);
375 + break;
376 + default:
377 + nd_log_daemon(NDLP_ERR, "Unknown msg type %u; ignoring", query->type);
378 + ok_to_send = false;
379 + break;
380 }
381 + if (ok_to_send)
382 + send_bin_msg(config->client, query);
383 aclk_query_free(query);
384 }
385
@@ -322,13 +387,11 @@ static void aclk_run_query_job(uv_work_t *req)
387 {
388 register_libuv_worker_jobs();
389
325 - worker_is_busy(UV_EVENT_ACLK_QUERY_EXECUTE);
326 -
390 struct aclk_query_payload *payload = req->data;
391 struct aclk_sync_config_s *config = payload->config;
392 aclk_query_t query = (aclk_query_t) payload->data;
393
331 - aclk_run_query(config, query);
394 + aclk_run_query(config, query, true);
395 worker_is_idle();
396 }
397
@@ -508,7 +571,7 @@ static void aclk_synchronization(void *arg)
571
572 if (execute_now) {
573 worker_is_busy(ACLK_QUERY_EXECUTE_SYNC);
511 - aclk_run_query(config, query);
574 + aclk_run_query(config, query, false);
575 freez(payload);
576 config->aclk_queries_running--;
577 }