summaryrefslogtreecommitdiffstats
path: root/src/streaming/rrdhost-status.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/streaming/rrdhost-status.c')
-rw-r--r--src/streaming/rrdhost-status.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/streaming/rrdhost-status.c b/src/streaming/rrdhost-status.c
new file mode 100644
index 000000000..c34fa693e
--- /dev/null
+++ b/src/streaming/rrdhost-status.c
@@ -0,0 +1,355 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rrdhost-status.h"
+
+const char *rrdhost_db_status_to_string(RRDHOST_DB_STATUS status) {
+ switch(status) {
+ default:
+ case RRDHOST_DB_STATUS_INITIALIZING:
+ return "initializing";
+
+ case RRDHOST_DB_STATUS_QUERYABLE:
+ return "online";
+ }
+}
+
+const char *rrdhost_db_liveness_to_string(RRDHOST_DB_LIVENESS status) {
+ switch(status) {
+ default:
+ case RRDHOST_DB_LIVENESS_STALE:
+ return "stale";
+
+ case RRDHOST_DB_LIVENESS_LIVE:
+ return "live";
+ }
+}
+
+const char *rrdhost_ingest_status_to_string(RRDHOST_INGEST_STATUS status) {
+ switch(status) {
+ case RRDHOST_INGEST_STATUS_ARCHIVED:
+ return "archived";
+
+ case RRDHOST_INGEST_STATUS_INITIALIZING:
+ return "initializing";
+
+ case RRDHOST_INGEST_STATUS_REPLICATING:
+ return "replicating";
+
+ case RRDHOST_INGEST_STATUS_ONLINE:
+ return "online";
+
+ default:
+ case RRDHOST_INGEST_STATUS_OFFLINE:
+ return "offline";
+ }
+}
+
+const char *rrdhost_ingest_type_to_string(RRDHOST_INGEST_TYPE type) {
+ switch(type) {
+ case RRDHOST_INGEST_TYPE_LOCALHOST:
+ return "localhost";
+
+ case RRDHOST_INGEST_TYPE_VIRTUAL:
+ return "virtual";
+
+ case RRDHOST_INGEST_TYPE_CHILD:
+ return "child";
+
+ default:
+ case RRDHOST_INGEST_TYPE_ARCHIVED:
+ return "archived";
+ }
+}
+
+const char *rrdhost_streaming_status_to_string(RRDHOST_STREAMING_STATUS status) {
+ switch(status) {
+ case RRDHOST_STREAM_STATUS_DISABLED:
+ return "disabled";
+
+ case RRDHOST_STREAM_STATUS_REPLICATING:
+ return "replicating";
+
+ case RRDHOST_STREAM_STATUS_ONLINE:
+ return "online";
+
+ default:
+ case RRDHOST_STREAM_STATUS_OFFLINE:
+ return "offline";
+ }
+}
+
+const char *rrdhost_ml_status_to_string(RRDHOST_ML_STATUS status) {
+ switch(status) {
+ case RRDHOST_ML_STATUS_RUNNING:
+ return "online";
+
+ case RRDHOST_ML_STATUS_OFFLINE:
+ return "offline";
+
+ default:
+ case RRDHOST_ML_STATUS_DISABLED:
+ return "disabled";
+ }
+}
+
+const char *rrdhost_ml_type_to_string(RRDHOST_ML_TYPE type) {
+ switch(type) {
+ case RRDHOST_ML_TYPE_SELF:
+ return "self";
+
+ case RRDHOST_ML_TYPE_RECEIVED:
+ return "received";
+
+ default:
+ case RRDHOST_ML_TYPE_DISABLED:
+ return "disabled";
+ }
+}
+
+const char *rrdhost_health_status_to_string(RRDHOST_HEALTH_STATUS status) {
+ switch(status) {
+ default:
+ case RRDHOST_HEALTH_STATUS_DISABLED:
+ return "disabled";
+
+ case RRDHOST_HEALTH_STATUS_INITIALIZING:
+ return "initializing";
+
+ case RRDHOST_HEALTH_STATUS_RUNNING:
+ return "online";
+ }
+}
+
+const char *rrdhost_dyncfg_status_to_string(RRDHOST_DYNCFG_STATUS status) {
+ switch(status) {
+ default:
+ case RRDHOST_DYNCFG_STATUS_UNAVAILABLE:
+ return "unavailable";
+
+ case RRDHOST_DYNCFG_STATUS_AVAILABLE:
+ return "online";
+ }
+}
+
+static NETDATA_DOUBLE rrdhost_sender_replication_completion_unsafe(RRDHOST *host, time_t now, size_t *instances) {
+ size_t charts = rrdhost_sender_replicating_charts(host);
+ NETDATA_DOUBLE completion;
+ if(!charts || !host->sender || !host->sender->replication.oldest_request_after_t)
+ completion = 100.0;
+ else if(!host->sender->replication.latest_completed_before_t || host->sender->replication.latest_completed_before_t < host->sender->replication.oldest_request_after_t)
+ completion = 0.0;
+ else {
+ time_t total = now - host->sender->replication.oldest_request_after_t;
+ time_t current = host->sender->replication.latest_completed_before_t - host->sender->replication.oldest_request_after_t;
+ completion = (NETDATA_DOUBLE) current * 100.0 / (NETDATA_DOUBLE) total;
+ }
+
+ *instances = charts;
+
+ return completion;
+}
+
+void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
+ memset(s, 0, sizeof(*s));
+
+ s->host = host;
+ s->now = now;
+
+ RRDHOST_FLAGS flags = __atomic_load_n(&host->flags, __ATOMIC_RELAXED);
+
+ // --- dyncfg ---
+
+ s->dyncfg.status = dyncfg_available_for_rrdhost(host) ? RRDHOST_DYNCFG_STATUS_AVAILABLE : RRDHOST_DYNCFG_STATUS_UNAVAILABLE;
+
+ // --- db ---
+
+ bool online = rrdhost_is_online(host);
+
+ rrdhost_retention(host, now, online, &s->db.first_time_s, &s->db.last_time_s);
+ s->db.metrics = host->rrdctx.metrics;
+ s->db.instances = host->rrdctx.instances;
+ s->db.contexts = dictionary_entries(host->rrdctx.contexts);
+ if(!s->db.first_time_s || !s->db.last_time_s || !s->db.metrics || !s->db.instances || !s->db.contexts ||
+ (flags & (RRDHOST_FLAG_PENDING_CONTEXT_LOAD)))
+ s->db.status = RRDHOST_DB_STATUS_INITIALIZING;
+ else
+ s->db.status = RRDHOST_DB_STATUS_QUERYABLE;
+
+ s->db.mode = host->rrd_memory_mode;
+
+ // --- ingest ---
+
+ s->ingest.since = MAX(host->child_connect_time, host->child_disconnected_time);
+ s->ingest.reason = (online) ? STREAM_HANDSHAKE_NEVER : host->rrdpush_last_receiver_exit_reason;
+
+ spinlock_lock(&host->receiver_lock);
+ s->ingest.hops = (host->system_info ? host->system_info->hops : (host == localhost) ? 0 : 1);
+ bool has_receiver = false;
+ if (host->receiver && !rrdhost_flag_check(host, RRDHOST_FLAG_RRDPUSH_RECEIVER_DISCONNECTED)) {
+ has_receiver = true;
+ s->ingest.replication.instances = rrdhost_receiver_replicating_charts(host);
+ s->ingest.replication.completion = host->rrdpush_receiver_replication_percent;
+ s->ingest.replication.in_progress = s->ingest.replication.instances > 0;
+
+ s->ingest.capabilities = host->receiver->capabilities;
+ s->ingest.peers = socket_peers(host->receiver->fd);
+ s->ingest.ssl = SSL_connection(&host->receiver->ssl);
+ }
+ spinlock_unlock(&host->receiver_lock);
+
+ if (online) {
+ if(s->db.status == RRDHOST_DB_STATUS_INITIALIZING)
+ s->ingest.status = RRDHOST_INGEST_STATUS_INITIALIZING;
+
+ else if (host == localhost || rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST)) {
+ s->ingest.status = RRDHOST_INGEST_STATUS_ONLINE;
+ s->ingest.since = netdata_start_time;
+ }
+
+ else if (s->ingest.replication.in_progress)
+ s->ingest.status = RRDHOST_INGEST_STATUS_REPLICATING;
+
+ else
+ s->ingest.status = RRDHOST_INGEST_STATUS_ONLINE;
+ }
+ else {
+ if (!s->ingest.since) {
+ s->ingest.status = RRDHOST_INGEST_STATUS_ARCHIVED;
+ s->ingest.since = s->db.last_time_s;
+ }
+
+ else
+ s->ingest.status = RRDHOST_INGEST_STATUS_OFFLINE;
+ }
+
+ if(host == localhost)
+ s->ingest.type = RRDHOST_INGEST_TYPE_LOCALHOST;
+ else if(has_receiver)
+ s->ingest.type = RRDHOST_INGEST_TYPE_CHILD;
+ else if(rrdhost_option_check(host, RRDHOST_OPTION_VIRTUAL_HOST))
+ s->ingest.type = RRDHOST_INGEST_TYPE_VIRTUAL;
+ else
+ s->ingest.type = RRDHOST_INGEST_TYPE_ARCHIVED;
+
+ s->ingest.id = host->rrdpush_receiver_connection_counter;
+
+ if(!s->ingest.since)
+ s->ingest.since = netdata_start_time;
+
+ if(s->ingest.status == RRDHOST_INGEST_STATUS_ONLINE)
+ s->db.liveness = RRDHOST_DB_LIVENESS_LIVE;
+ else
+ s->db.liveness = RRDHOST_DB_LIVENESS_STALE;
+
+ // --- stream ---
+
+ if (!host->sender) {
+ s->stream.status = RRDHOST_STREAM_STATUS_DISABLED;
+ s->stream.hops = s->ingest.hops + 1;
+ }
+ else {
+ sender_lock(host->sender);
+
+ s->stream.since = host->sender->last_state_since_t;
+ s->stream.peers = socket_peers(host->sender->rrdpush_sender_socket);
+ s->stream.ssl = SSL_connection(&host->sender->ssl);
+
+ memcpy(s->stream.sent_bytes_on_this_connection_per_type,
+ host->sender->sent_bytes_on_this_connection_per_type,
+ MIN(sizeof(s->stream.sent_bytes_on_this_connection_per_type),
+ sizeof(host->sender->sent_bytes_on_this_connection_per_type)));
+
+ if (rrdhost_flag_check(host, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED)) {
+ s->stream.hops = host->sender->hops;
+ s->stream.reason = STREAM_HANDSHAKE_NEVER;
+ s->stream.capabilities = host->sender->capabilities;
+
+ s->stream.replication.completion = rrdhost_sender_replication_completion_unsafe(host, now, &s->stream.replication.instances);
+ s->stream.replication.in_progress = s->stream.replication.instances > 0;
+
+ if(s->stream.replication.in_progress)
+ s->stream.status = RRDHOST_STREAM_STATUS_REPLICATING;
+ else
+ s->stream.status = RRDHOST_STREAM_STATUS_ONLINE;
+
+ s->stream.compression = host->sender->compressor.initialized;
+ }
+ else {
+ s->stream.status = RRDHOST_STREAM_STATUS_OFFLINE;
+ s->stream.hops = s->ingest.hops + 1;
+ s->stream.reason = host->sender->exit.reason;
+ }
+
+ sender_unlock(host->sender);
+ }
+
+ s->stream.id = host->rrdpush_sender_connection_counter;
+
+ if(!s->stream.since)
+ s->stream.since = netdata_start_time;
+
+ // --- ml ---
+
+ if(ml_host_get_host_status(host, &s->ml.metrics)) {
+ s->ml.type = RRDHOST_ML_TYPE_SELF;
+
+ if(s->ingest.status == RRDHOST_INGEST_STATUS_OFFLINE || s->ingest.status == RRDHOST_INGEST_STATUS_ARCHIVED)
+ s->ml.status = RRDHOST_ML_STATUS_OFFLINE;
+ else
+ s->ml.status = RRDHOST_ML_STATUS_RUNNING;
+ }
+ else if(stream_has_capability(&s->ingest, STREAM_CAP_DATA_WITH_ML)) {
+ s->ml.type = RRDHOST_ML_TYPE_RECEIVED;
+ s->ml.status = RRDHOST_ML_STATUS_RUNNING;
+ }
+ else {
+ // does not receive ML, does not run ML
+ s->ml.type = RRDHOST_ML_TYPE_DISABLED;
+ s->ml.status = RRDHOST_ML_STATUS_DISABLED;
+ }
+
+ // --- health ---
+
+ if(host->health.health_enabled) {
+ if(flags & RRDHOST_FLAG_PENDING_HEALTH_INITIALIZATION)
+ s->health.status = RRDHOST_HEALTH_STATUS_INITIALIZING;
+ else {
+ s->health.status = RRDHOST_HEALTH_STATUS_RUNNING;
+
+ RRDCALC *rc;
+ foreach_rrdcalc_in_rrdhost_read(host, rc) {
+ if (unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
+ continue;
+
+ switch (rc->status) {
+ default:
+ case RRDCALC_STATUS_REMOVED:
+ break;
+
+ case RRDCALC_STATUS_CLEAR:
+ s->health.alerts.clear++;
+ break;
+
+ case RRDCALC_STATUS_WARNING:
+ s->health.alerts.warning++;
+ break;
+
+ case RRDCALC_STATUS_CRITICAL:
+ s->health.alerts.critical++;
+ break;
+
+ case RRDCALC_STATUS_UNDEFINED:
+ s->health.alerts.undefined++;
+ break;
+
+ case RRDCALC_STATUS_UNINITIALIZED:
+ s->health.alerts.uninitialized++;
+ break;
+ }
+ }
+ foreach_rrdcalc_in_rrdhost_done(rc);
+ }
+ }
+ else
+ s->health.status = RRDHOST_HEALTH_STATUS_DISABLED;
+}