@cryptotaxi247 / netdata-1 / commits / bb84d2281

Fix netdatacli ping command (#21965)

* Refactor API endpoints to use `netdata_ready_load()` and enhance `ping` command to check agent initialization status. * Adjust reply prefix for ping command * Update src/cli/README.md Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud> * Address review comments * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Cleanup description * Update src/cli/README.md Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --------- Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

Stelios Fragkakis committed Mar 19, 2026 at 09:11 UTC bb84d228173e55075cb0292480b74a4146419546
11 files changed +31 -15
src/cli/README.md
+2 -2
@@ -10,12 +10,12 @@ Available commands:
10 |---------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
11 | `help` | Display usage information and exit. |
12 | `reload-health` | Reloads the Netdata health configuration, updating alerts based on changes made to configuration files. |
13 -| `reload-labels` | Reloads [host labels](/docs/netdata-agent/configuration/organize-systems-metrics-and-alerts.md#create-custom-labels) from netdata.conf. |
13 +| `reload-labels` | Reloads [host labels](/docs/netdata-agent/configuration/organize-systems-metrics-and-alerts.md#create-custom-labels) from netdata.conf. |
14 | `reopen-logs` | Close and reopen log files. |
15 | `shutdown-agent` | Gracefully shut down the Netdata Agent. |
16 | `fatal-agent` | Log the current state and forcefully halt the Netdata Agent. |
17 | `reload-claiming-state` | Reload the Agent's claiming state from disk. |
18 -| `ping` | Checks the Agent's status. If the Agent is alive, it exits with status code 0 and prints 'pong' to standard output. Exits with status code 255 otherwise. |
18 +| `ping` | Verifies whether the Agent is ready. Outputs `pong` when the Agent command server can be contacted. Exit code `0` when the Agent is ready to receive commands. Exit code `1` while the Agent is still initializing. Exit code `255` if the Agent is unreachable |
19 | `aclk-state [json]` | Return the current state of ACLK and Cloud connection. Optionally in JSON. |
20 | `dumpconfig` | Display the current netdata.conf configuration. |
21 | `mark-stale-nodes-ephemeral <node_id \| machine_guid \| hostname \| ALL_NODES>` | Marks one or all disconnected nodes, including virtual nodes, as [ephemeral](/docs/nodes-ephemerality.md), while keeping their previously collected metrics data available for queries on both this Netdata Agent dashboard and Netdata Cloud.[^1][^2] |
src/daemon/commands.c
+12 -3
@@ -33,6 +33,14 @@ struct command_context {
33 unsigned command_string_size;
34 };
35
36 +static inline char command_reply_prefix(const struct command_context *cmd_ctx, cmd_status_t status)
37 +{
38 + if (cmd_ctx->idx == CMD_PING)
39 + return CMD_PREFIX_INFO;
40 +
41 + return cmd_prefix_by_status[status];
42 +}
43 +
44 /* Forward declarations */
45 static cmd_status_t cmd_help_execute(char *args, char **message);
46 static cmd_status_t cmd_reload_health_execute(char *args, char **message);
@@ -61,7 +69,7 @@ static command_info_t command_info_array[] = {
69 {"reload-labels", "", "Reload all localhost labels.", cmd_reload_labels_execute, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_FULL}, // reload the labels
70 {"read-config", "", "", cmd_read_config_execute, CMD_TYPE_CONCURRENT, CMD_INIT_STATUS_FULL},
71 {"write-config", "", "", cmd_write_config_execute, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_FULL},
64 - {"ping", "", "Return with 'pong' if agent is alive.", cmd_ping_execute, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_INIT}, // ping command
72 + {"ping", "", "Return with 'pong'; exit 0 when ready, 1 while initializing, 255 if the agent cannot be contacted.", cmd_ping_execute, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_INIT}, // ping command
73 {"aclk-state", "[json]", "Returns current state of ACLK and Netdata Cloud connection. (optionally in json).", cmd_aclk_state, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_FULL},
74 {"version", "", "Returns the netdata version.", cmd_version, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_INIT},
75 {"dumpconfig", "", "Returns the current netdata.conf on stdout.", cmd_dumpconfig, CMD_TYPE_ORTHOGONAL, CMD_INIT_STATUS_FULL},
@@ -309,7 +317,7 @@ static cmd_status_t cmd_ping_execute(char *args, char **message)
317
318 *message = strdupz("pong");
319
312 - return CMD_STATUS_SUCCESS;
320 + return netdata_ready_load() ? CMD_STATUS_SUCCESS : CMD_STATUS_FAILURE;
321 }
322
323 static cmd_status_t cmd_aclk_state(char *args, char **message)
@@ -585,7 +593,7 @@ static void send_command_reply(struct command_context *cmd_ctx, cmd_status_t sta
593 add_char_to_command_reply(reply_string, &reply_string_size, '\0');
594
595 if (message) {
588 - add_char_to_command_reply(reply_string, &reply_string_size, cmd_prefix_by_status[status]);
596 + add_char_to_command_reply(reply_string, &reply_string_size, command_reply_prefix(cmd_ctx, status));
597 add_string_to_command_reply(reply_string, &reply_string_size, message);
598 }
599
@@ -727,6 +735,7 @@ static void connection_cb(uv_stream_t *server, int status)
735
736 /* combined allocation of client pipe and command context */
737 cmd_ctx = mallocz(sizeof(*cmd_ctx));
738 + cmd_ctx->idx = CMD_HELP;
739 client = (uv_pipe_t *)cmd_ctx;
740 ret = uv_pipe_init(server->loop, client, 1);
741 if (ret) {
src/daemon/common.h
+8
@@ -101,6 +101,14 @@ void system_tz_free(SYSTEM_TZ *tz);
101 extern bool netdata_ready;
102 extern time_t netdata_start_time;
103
104 +static inline bool netdata_ready_load(void) {
105 + return __atomic_load_n(&netdata_ready, __ATOMIC_ACQUIRE);
106 +}
107 +
108 +static inline void netdata_ready_store(bool ready) {
109 + __atomic_store_n(&netdata_ready, ready, __ATOMIC_RELEASE);
110 +}
111 +
112 void set_environment_for_plugins_and_scripts(void);
113
114 #ifdef __cplusplus
src/daemon/main.c
+2 -2
@@ -277,7 +277,7 @@ int netdata_main(int argc, char **argv) {
277
278 static_threads = static_threads_get();
279
280 - netdata_ready = false;
280 + netdata_ready_store(false);
281 // set the name for logging
282 program_name = "netdata";
283
@@ -1156,7 +1156,7 @@ int netdata_main(int argc, char **argv) {
1156 (ready_ut - started_ut) / USEC_PER_MS, median_start_time / USEC_PER_MS);
1157
1158 cleanup_agent_event_log();
1159 - netdata_ready = true;
1159 + netdata_ready_store(true);
1160
1161 // ----------------------------------------------------------------------------------------------------------------
1162
src/web/api/v1/api_v1_aclk.c
+1 -2
@@ -5,7 +5,7 @@
5 int api_v1_aclk(RRDHOST *host, struct web_client *w, char *url) {
6 UNUSED(url);
7 UNUSED(host);
8 - if (!netdata_ready) return HTTP_RESP_SERVICE_UNAVAILABLE;
8 + if (!netdata_ready_load()) return HTTP_RESP_SERVICE_UNAVAILABLE;
9
10 BUFFER *wb = w->response.data;
11 buffer_flush(wb);
@@ -17,4 +17,3 @@ int api_v1_aclk(RRDHOST *host, struct web_client *w, char *url) {
17 buffer_no_cacheable(wb);
18 return HTTP_RESP_OK;
19 }
20 -
src/web/api/v1/api_v1_dbengine.c
+1 -1
@@ -71,7 +71,7 @@ static void web_client_api_v1_dbengine_stats_for_tier(BUFFER *wb, size_t tier) {
71 }
72
73 int api_v1_dbengine_stats(RRDHOST *host __maybe_unused, struct web_client *w, char *url __maybe_unused) {
74 - if (!netdata_ready)
74 + if (!netdata_ready_load())
75 return HTTP_RESP_SERVICE_UNAVAILABLE;
76
77 BUFFER *wb = w->response.data;
src/web/api/v1/api_v1_function.c
+1 -1
@@ -3,7 +3,7 @@
3 #include "api_v1_calls.h"
4
5 int api_v1_function(RRDHOST *host, struct web_client *w, char *url) {
6 - if (!netdata_ready)
6 + if (!netdata_ready_load())
7 return HTTP_RESP_SERVICE_UNAVAILABLE;
8
9 int timeout = 0;
src/web/api/v1/api_v1_functions.c
+1 -1
@@ -3,7 +3,7 @@
3 #include "api_v1_calls.h"
4
5 int api_v1_functions(RRDHOST *host, struct web_client *w, char *url __maybe_unused) {
6 - if (!netdata_ready)
6 + if (!netdata_ready_load())
7 return HTTP_RESP_SERVICE_UNAVAILABLE;
8
9 BUFFER *wb = w->response.data;
src/web/api/v1/api_v1_info.c
+1 -1
@@ -165,7 +165,7 @@ static int web_client_api_request_v1_info_fill_buffer(RRDHOST *host, BUFFER *wb)
165
166 int api_v1_info(RRDHOST *host, struct web_client *w, char *url) {
167 (void)url;
168 - if (!netdata_ready) return HTTP_RESP_SERVICE_UNAVAILABLE;
168 + if (!netdata_ready_load()) return HTTP_RESP_SERVICE_UNAVAILABLE;
169 BUFFER *wb = w->response.data;
170 buffer_flush(wb);
171 wb->content_type = CT_APPLICATION_JSON;
src/web/api/v1/api_v1_ml_info.c
+1 -1
@@ -6,7 +6,7 @@ int api_v1_ml_info(RRDHOST *host, struct web_client *w, char *url) {
6 (void) url;
7 #if defined(ENABLE_ML)
8
9 - if (!netdata_ready)
9 + if (!netdata_ready_load())
10 return HTTP_RESP_SERVICE_UNAVAILABLE;
11
12 BUFFER *wb = w->response.data;
src/web/api/v2/api_v2_weights.c
+1 -1
@@ -3,7 +3,7 @@
3 #include "api_v2_calls.h"
4
5 int web_client_api_request_weights(RRDHOST *host, struct web_client *w, char *url, WEIGHTS_METHOD method, WEIGHTS_FORMAT format, size_t api_version) {
6 - if (!netdata_ready)
6 + if (!netdata_ready_load())
7 return HTTP_RESP_SERVICE_UNAVAILABLE;
8
9 time_t baseline_after = 0, baseline_before = 0, after = 0, before = 0;