summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@netdata.cloud>2022-07-15 01:37:08 +0300
committerCosta Tsaousis <costa@netdata.cloud>2022-07-15 01:37:08 +0300
commit10dc1c304e53e1378f516a92c2ad197829ee62a3 (patch)
tree09555d08e0d0175901c4b18b83f32b20b951847d
parent1de3a708e0094f5d96b085e39acd703158dbf8f3 (diff)
full contexts API; updated swagger
-rw-r--r--database/rrdcontext.c119
-rw-r--r--database/rrdcontext.h8
-rw-r--r--libnetdata/dictionary/dictionary.c43
-rw-r--r--web/api/netdata-swagger.json194
-rw-r--r--web/api/netdata-swagger.yaml140
-rw-r--r--web/api/web_api_v1.c80
6 files changed, 518 insertions, 66 deletions
diff --git a/database/rrdcontext.c b/database/rrdcontext.c
index 6fdbc78dba..066f0955db 100644
--- a/database/rrdcontext.c
+++ b/database/rrdcontext.c
@@ -92,14 +92,14 @@ typedef enum {
if(likely(!((obj)->flags & RRD_FLAG_COLLECTED))) \
(obj)->flags |= (RRD_FLAG_COLLECTED | RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED | RRD_FLAG_UPDATED); \
if(likely( ((obj)->flags & (RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED)))) \
- (obj)->flags &= ~(RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED); \
+ (obj)->flags &= ~(RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED); \
} while(0)
#define rrd_flag_set_archived(obj) do { \
if(likely(!((obj)->flags & RRD_FLAG_ARCHIVED))) \
(obj)->flags |= (RRD_FLAG_ARCHIVED | RRD_FLAG_UPDATE_REASON_STOPPED_BEING_COLLECTED | RRD_FLAG_UPDATED); \
if(likely( ((obj)->flags & (RRD_FLAG_COLLECTED | RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED)))) \
- (obj)->flags &= ~(RRD_FLAG_COLLECTED | RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED); \
+ (obj)->flags &= ~(RRD_FLAG_COLLECTED | RRD_FLAG_UPDATE_REASON_STARTED_BEING_COLLECTED); \
} while(0)
#define rrd_flag_is_collected(obj) ((obj)->flags & RRD_FLAG_COLLECTED)
@@ -163,15 +163,15 @@ typedef struct rrdinstance {
STRING *title;
STRING *units;
STRING *family;
- size_t priority;
+ uint32_t priority;
RRDSET_TYPE chart_type;
- int update_every; // data collection frequency
- RRDSET *rrdset; // pointer to RRDSET when collected, or NULL
-
+ RRD_FLAGS flags; // flags related to this instance
time_t first_time_t;
time_t last_time_t;
- RRD_FLAGS flags; // flags related to this instance
+
+ int update_every; // data collection frequency
+ RRDSET *rrdset; // pointer to RRDSET when collected, or NULL
DICTIONARY *rrdlabels; // linked to RRDSET->state->chart_labels or own version
@@ -186,23 +186,25 @@ typedef struct rrdcontext {
STRING *title;
STRING *units;
STRING *family;
+ uint32_t priority;
RRDSET_TYPE chart_type;
- size_t priority;
-
+ RRD_FLAGS flags;
time_t first_time_t;
time_t last_time_t;
- RRD_FLAGS flags;
VERSIONED_CONTEXT_DATA hub;
DICTIONARY *rrdinstances;
RRDHOST *rrdhost;
- RRD_FLAGS last_queued_flags;
- usec_t last_queued_ut;
- usec_t last_delay_calc_ut;
- usec_t scheduled_dispatch_ut;
+ struct {
+ RRD_FLAGS queued_flags; // the last flags that triggered the queueing
+ usec_t queued_ut; // the last time this was queued
+ usec_t delay_calc_ut; // the last time we calculated the scheduled_dispatched_ut
+ usec_t scheduled_dispatch_ut; // the time it was/is scheduled to be sent
+ usec_t dequeued_ut; // the last time we sent (or deduped) this context
+ } queue;
netdata_mutex_t mutex;
} RRDCONTEXT;
@@ -268,6 +270,8 @@ static void rrdcontext_recalculate_host_retention(RRDHOST *host, RRD_FLAGS reaso
#define rrdcontext_version_hash(host) rrdcontext_version_hash_with_callback(host, NULL, false, NULL)
static uint64_t rrdcontext_version_hash_with_callback(RRDHOST *host, void (*callback)(RRDCONTEXT *, bool, void *), bool snapshot, void *bundle);
+void rrdcontext_delete_from_sql_unsafe(RRDCONTEXT *rc);
+
#define rrdcontext_lock(rc) netdata_mutex_lock(&((rc)->mutex))
#define rrdcontext_unlock(rc) netdata_mutex_unlock(&((rc)->mutex))
@@ -1208,8 +1212,14 @@ static void rrdcontext_message_send_unsafe(RRDCONTEXT *rc, bool snapshot __maybe
#endif
// store it to SQL
- if(ctx_store_context(&rc->rrdhost->host_uuid, &rc->hub) != 0)
- error("RRDCONTEXT: failed to save context '%s' version %lu to SQL.", rc->hub.id, rc->hub.version);
+
+ if(rc->flags & RRD_FLAG_DELETED) {
+ rrdcontext_delete_from_sql_unsafe(rc);
+ }
+ else {
+ if (ctx_store_context(&rc->rrdhost->host_uuid, &rc->hub) != 0)
+ error("RRDCONTEXT: failed to save context '%s' version %lu to SQL.", rc->hub.id, rc->hub.version);
+ }
}
static bool check_if_cloud_version_changed_unsafe(RRDCONTEXT *rc, bool sending) {
@@ -1252,7 +1262,7 @@ static bool check_if_cloud_version_changed_unsafe(RRDCONTEXT *rc, bool sending)
if(unlikely(id_changed || title_changed || units_changed || family_changed || chart_type_changed || priority_changed || first_time_changed || last_time_changed || deleted_changed)) {
- internal_error(true, "RRDCONTEXT: %s NEW VERSION '%s'%s, version %zu, title '%s'%s, units '%s'%s, family '%s'%s, chart type '%s'%s, priority %lu%s, first_time_t %ld%s, last_time_t %ld%s, deleted '%s'%s, (queued for %llu ms, expected %llu ms)",
+ internal_error(true, "RRDCONTEXT: %s NEW VERSION '%s'%s, version %zu, title '%s'%s, units '%s'%s, family '%s'%s, chart type '%s'%s, priority %u%s, first_time_t %ld%s, last_time_t %ld%s, deleted '%s'%s, (queued for %llu ms, expected %llu ms)",
sending?"SENDING":"QUEUE",
string2str(rc->id), id_changed ? " (CHANGED)" : "",
rc->version,
@@ -1264,8 +1274,8 @@ static bool check_if_cloud_version_changed_unsafe(RRDCONTEXT *rc, bool sending)
rc->first_time_t, first_time_changed ? " (CHANGED)" : "",
rrd_flag_is_collected(rc) ? 0 : rc->last_time_t, last_time_changed ? " (CHANGED)" : "",
(rc->flags & RRD_FLAG_DELETED) ? "true" : "false", deleted_changed ? " (CHANGED)" : "",
- sending ? (now_realtime_usec() - rc->last_queued_ut) / USEC_PER_MS : 0,
- sending ? (rc->scheduled_dispatch_ut - rc->last_queued_ut) / USEC_PER_SEC : 0
+ sending ? (now_realtime_usec() - rc->queue.queued_ut) / USEC_PER_MS : 0,
+ sending ? (rc->queue.scheduled_dispatch_ut - rc->queue.queued_ut) / USEC_PER_SEC : 0
);
return true;
}
@@ -1608,8 +1618,8 @@ static void rrdcontext_trigger_updates(RRDCONTEXT *rc, bool force, RRD_FLAGS rea
if(check_if_cloud_version_changed_unsafe(rc, false)) {
rc->version = rrdcontext_get_next_version(rc);
- rc->last_queued_ut = now_realtime_usec();
- rc->last_queued_flags |= rc->flags;
+ rc->queue.queued_ut = now_realtime_usec();
+ rc->queue.queued_flags |= rc->flags;
if(!(rc->flags & RRD_FLAG_QUEUED)) {
rc->flags |= RRD_FLAG_QUEUED;
dictionary_set((DICTIONARY *)rc->rrdhost->rrdctx_queue, string2str(rc->id), rc, sizeof(*rc));
@@ -1791,6 +1801,7 @@ void rrdcontext_hub_checkpoint_command(void *ptr) {
contexts_snapshot_t bundle = contexts_snapshot_new(host->aclk_state.claimed_id, uuid, our_version_hash);
// calculate version hash and pack all the messages together in one go
+ rrdcontext_recalculate_host_retention(host, RRD_FLAG_NONE, -1);
our_version_hash = rrdcontext_version_hash_with_callback(host, rrdcontext_message_send_unsafe, true, bundle);
// update the version
@@ -1918,7 +1929,7 @@ static inline int rrdinstance_to_json_callback(const char *id, void *value, void
",\n\t\t\t\t\t\"units\":\"%s\""
",\n\t\t\t\t\t\"family\":\"%s\""
",\n\t\t\t\t\t\"chart_type\":\"%s\""
- ",\n\t\t\t\t\t\"priority\":%zu"
+ ",\n\t\t\t\t\t\"priority\":%u"
",\n\t\t\t\t\t\"update_every\":%d"
",\n\t\t\t\t\t\"first_time_t\":%ld"
",\n\t\t\t\t\t\"last_time_t\":%ld"
@@ -1981,20 +1992,25 @@ static inline int rrdcontext_to_json_callback(const char *id, void *value, void
else
buffer_strcat(wb, "\n");
- buffer_sprintf(wb, "\t\t\"%s\": {", id);
+ if(options & RRDCONTEXT_OPTION_SKIP_ID)
+ buffer_sprintf(wb, "\t\t\{");
+ else
+ buffer_sprintf(wb, "\t\t\"%s\": {", id);
buffer_sprintf(wb,
"\n\t\t\t\"version\":%lu"
+ ",\n\t\t\t\"hub_version\":%lu"
",\n\t\t\t\"title\":\"%s\""
",\n\t\t\t\"units\":\"%s\""
",\n\t\t\t\"family\":\"%s\""
",\n\t\t\t\"chart_type\":\"%s\""
- ",\n\t\t\t\"priority\":%zu"
+ ",\n\t\t\t\"priority\":%u"
",\n\t\t\t\"first_time_t\":%ld"
",\n\t\t\t\"last_time_t\":%ld"
",\n\t\t\t\"collected\":%s"
",\n\t\t\t\"deleted\":%s"
, rc->version
+ , rc->hub.version
, string2str(rc->title)
, string2str(rc->units)
, string2str(rc->family)
@@ -2012,12 +2028,19 @@ static inline int rrdcontext_to_json_callback(const char *id, void *value, void
buffer_strcat(wb, "\"");
}
- if(options & RRDCONTEXT_OPTION_SHOW_QUEUE_REASONS) {
- if (rc->flags & RRD_FLAG_QUEUED) {
- buffer_strcat(wb, ",\n\t\t\t\"queued_reasons\":\"");
- rrd_reasons_to_buffer(rc->last_queued_flags, wb);
- buffer_strcat(wb, "\"");
- }
+ if(options & RRDCONTEXT_OPTION_SHOW_QUEUED) {
+ buffer_strcat(wb, ",\n\t\t\t\"queued_reasons\":\"");
+ rrd_reasons_to_buffer(rc->queue.queued_flags, wb);
+ buffer_strcat(wb, "\"");
+
+ buffer_sprintf(wb,
+ ",\n\t\t\t\"last_queued\":%llu"
+ ",\n\t\t\t\"scheduled_dispatch\":%llu"
+ ",\n\t\t\t\"last_dequeued\":%llu"
+ , rc->queue.queued_ut / USEC_PER_SEC
+ , rc->queue.scheduled_dispatch_ut / USEC_PER_SEC
+ , rc->queue.dequeued_ut / USEC_PER_SEC
+ );
}
if(options & (RRDCONTEXT_OPTION_SHOW_INSTANCES|RRDCONTEXT_OPTION_SHOW_METRICS)) {
@@ -2036,7 +2059,24 @@ static inline int rrdcontext_to_json_callback(const char *id, void *value, void
return 1;
}
-void rrdcontexts_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS options) {
+int rrdcontext_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS options, const char *context) {
+ RRDCONTEXT_ACQUIRED *rca = (RRDCONTEXT_ACQUIRED *)dictionary_get_and_acquire_item((DICTIONARY *)host->rrdctx, context);
+ if(!rca) return HTTP_RESP_NOT_FOUND;
+
+ RRDCONTEXT *rc = rrdcontext_acquired_value(rca);
+
+ struct rrdcontext_to_json t = {
+ .wb = wb,
+ .options = options|RRDCONTEXT_OPTION_SKIP_ID,
+ .written = 0,
+ };
+ rrdcontext_to_json_callback(context, rc, &t);
+
+ rrdcontext_release(rca);
+ return HTTP_RESP_OK;
+}
+
+int rrdcontexts_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS options) {
char node_uuid[UUID_STR_LEN];
uuid_unparse(*host->node_id, node_uuid);
@@ -2067,6 +2107,8 @@ void rrdcontexts_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS o
// close contexts, close main
buffer_strcat(wb, "\n\t}\n}");
+
+ return HTTP_RESP_OK;
}
// ----------------------------------------------------------------------------
@@ -2161,10 +2203,10 @@ void rrdhost_load_rrdcontext_data(RRDHOST *host) {
static inline usec_t rrdcontext_queued_dispatch_ut(RRDCONTEXT *rc, usec_t now_ut) {
- if(likely(rc->last_delay_calc_ut >= rc->last_queued_ut))
- return rc->scheduled_dispatch_ut;
+ if(likely(rc->queue.delay_calc_ut >= rc->queue.queued_ut))
+ return rc->queue.scheduled_dispatch_ut;
- RRD_FLAGS flags = rc->last_queued_flags;
+ RRD_FLAGS flags = rc->queue.queued_flags;
usec_t delay = LONG_MAX;
int i;
@@ -2181,8 +2223,8 @@ static inline usec_t rrdcontext_queued_dispatch_ut(RRDCONTEXT *rc, usec_t now_ut
delay = 60 * USEC_PER_SEC;
}
- rc->last_delay_calc_ut = now_ut;
- usec_t dispatch_ut = rc->scheduled_dispatch_ut = rc->last_queued_ut + delay;
+ rc->queue.delay_calc_ut = now_ut;
+ usec_t dispatch_ut = rc->queue.scheduled_dispatch_ut = rc->queue.queued_ut + delay;
return dispatch_ut;
}
@@ -2297,7 +2339,8 @@ void rrdcontext_delete_from_sql_unsafe(RRDCONTEXT *rc) {
rc->hub.family = string2str(rc->family);
// delete it from SQL
- ctx_delete_context(&rc->rrdhost->host_uuid, &rc->hub);
+ if(ctx_delete_context(&rc->rrdhost->host_uuid, &rc->hub) != 0)
+ error("RRDCONTEXT: failed to delete context '%s' version %lu from SQL.", rc->hub.id, rc->hub.version);
}
static void rrdcontext_garbage_collect(void) {
@@ -2430,7 +2473,7 @@ void *rrdcontext_main(void *ptr) {
rrdcontext_message_send_unsafe(rc, false, bundle);
messages_added++;
- rc->last_queued_flags = RRD_FLAG_NONE;
+ rc->queue.dequeued_ut = now_ut;
}
else
rc->version = rc->hub.version;
diff --git a/database/rrdcontext.h b/database/rrdcontext.h
index a84986f2a9..590fa20c2e 100644
--- a/database/rrdcontext.h
+++ b/database/rrdcontext.h
@@ -39,12 +39,16 @@ typedef enum {
RRDCONTEXT_OPTION_SHOW_METRICS = (1 << 0),
RRDCONTEXT_OPTION_SHOW_INSTANCES = (1 << 1),
RRDCONTEXT_OPTION_SHOW_LABELS = (1 << 2),
- RRDCONTEXT_OPTION_SHOW_QUEUE_REASONS = (1 << 3),
+ RRDCONTEXT_OPTION_SHOW_QUEUED = (1 << 3),
RRDCONTEXT_OPTION_SHOW_FLAGS = (1 << 4),
RRDCONTEXT_OPTION_SHOW_DELETED = (1 << 5),
+ RRDCONTEXT_OPTION_SKIP_ID = (1 << 31), // internal use
} RRDCONTEXT_TO_JSON_OPTIONS;
-extern void rrdcontexts_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS options);
+#define RRDCONTEXT_OPTIONS_ALL (RRDCONTEXT_OPTION_SHOW_METRICS|RRDCONTEXT_OPTION_SHOW_INSTANCES|RRDCONTEXT_OPTION_SHOW_LABELS|RRDCONTEXT_OPTION_SHOW_QUEUED|RRDCONTEXT_OPTION_SHOW_FLAGS|RRDCONTEXT_OPTION_SHOW_DELETED)
+
+extern int rrdcontext_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS options, const char *context);
+extern int rrdcontexts_to_json(RRDHOST *host, BUFFER *wb, RRDCONTEXT_TO_JSON_OPTIONS options);
// ----------------------------------------------------------------------------
// public API for rrddims
diff --git a/libnetdata/dictionary/dictionary.c b/libnetdata/dictionary/dictionary.c
index 0417c10906..f1a9f2f82d 100644
--- a/libnetdata/dictionary/dictionary.c
+++ b/libnetdata/dictionary/dictionary.c
@@ -29,6 +29,8 @@ typedef enum name_value_flags {
NAME_VALUE_FLAG_NAME_IS_ALLOCATED = (1 << 0), // the name pointer is a STRING
NAME_VALUE_FLAG_DELETED = (1 << 1), // this item is deleted, so it is not available for traversal
NAME_VALUE_FLAG_NEW_OR_UPDATED = (1 << 2), // this item is new or just updated (used by the react callback)
+
+ // IMPORTANT: IF YOU ADD ANOTHER FLAG, YOU NEED TO ALLOCATE ANOTHER BIT TO FLAGS IN NAME_VALUE !!!
} NAME_VALUE_FLAGS;
/*
@@ -47,17 +49,15 @@ typedef struct name_value {
struct name_value *next; // a double linked list to allow fast insertions and deletions
struct name_value *prev;
- size_t name_len; // the size of the name, including the terminating zero
- size_t value_len; // the size of the value (assumed binary)
+ uint32_t refcount; // the reference counter
+ uint32_t value_len:29; // the size of the value (assumed binary)
+ uint8_t flags:3; // the flags for this item
void *value; // the value of the dictionary item
union {
STRING *string_name; // the name of the dictionary item
char *caller_name; // the user supplied string pointer
};
-
- int refcount; // the reference counter
- NAME_VALUE_FLAGS flags; // the flags for this item
} NAME_VALUE;
struct dictionary {
@@ -441,18 +441,23 @@ static int reference_counter_acquire(DICTIONARY *dict, NAME_VALUE *nv) {
return refcount;
}
-static int reference_counter_release(DICTIONARY *dict, NAME_VALUE *nv, bool can_get_write_lock) {
+static uint32_t reference_counter_release(DICTIONARY *dict, NAME_VALUE *nv, bool can_get_write_lock) {
// this function may be called without any lock on the dictionary
// or even when someone else has a write lock on the dictionary
// so, we cannot check for EXCLUSIVE ACCESS
- int refcount;
+ uint32_t refcount;
if(likely(dict->flags & DICTIONARY_FLAG_SINGLE_THREADED))
- refcount = --nv->refcount;
+ refcount = nv->refcount--;
else
- refcount = __atomic_sub_fetch(&nv->refcount, 1, __ATOMIC_SEQ_CST);
+ refcount = __atomic_fetch_sub(&nv->refcount, 1, __ATOMIC_SEQ_CST);
if(refcount == 0) {
+ internal_error(true, "DICTIONARY: attempted to release item without references: '%s' on dictionary created by %s() (%zu@%s)", namevalue_get_name(nv), dict->creation_function, dict->creation_line, dict->creation_file);
+ fatal("DICTIONARY: attempted to release item without references: '%s'", namevalue_get_name(nv));
+ }
+
+ if(refcount == 1) {
if((nv->flags & NAME_VALUE_FLAG_DELETED))
DICTIONARY_STATS_PENDING_DELETES_PLUS1(dict);
@@ -469,11 +474,6 @@ static int reference_counter_release(DICTIONARY *dict, NAME_VALUE *nv, bool can_
dictionary_unlock(dict, DICTIONARY_LOCK_WRITE);
}
- if(refcount < 0) {
- internal_error(true, "DICTIONARY: reference counter is negative on item '%s' on dictionary created by %s() (%zu@%s)", namevalue_get_name(nv), dict->creation_function, dict->creation_line, dict->creation_file);
- fatal("DICTIONARY: reference counter is negative on item '%s'", namevalue_get_name(nv));
- }
-
return refcount;
}
@@ -716,7 +716,6 @@ static NAME_VALUE *namevalue_create_unsafe(DICTIONARY *dict, const char *name, s
nv->refcount = 0;
nv->flags = NAME_VALUE_FLAG_NONE;
- nv->name_len = name_len;
nv->value_len = value_len;
allocated += namevalue_set_name(dict, nv, name, name_len);
@@ -1439,9 +1438,9 @@ typedef struct string_entry {
#ifdef DICTIONARY_WITH_AVL
avl_t avl_node;
#endif
- volatile int refcount; // how many times this string is used
- size_t length; // the string length with the terminating '\0'
- const char str[]; // the string itself
+ uint32_t length; // the string length with the terminating '\0'
+ uint32_t refcount; // how many times this string is used
+ const char str[]; // the string itself
} STRING_ENTRY;
#ifdef DICTIONARY_WITH_AVL
@@ -1533,6 +1532,10 @@ void string_freez(STRING *string) {
netdata_mutex_lock(&string_mutex);
STRING_ENTRY *se = (STRING_ENTRY *)string;
+
+ if(se->refcount == 0)
+ fatal("STRING: tried to free string that has zero references.");
+
se->refcount--;
if(unlikely(se->refcount == 0)) {
if(hashtable_delete_unsafe(&string_dictionary, se->str, se->length, se) == 0)
@@ -1976,7 +1979,7 @@ static int check_name_value_callback(const char *name, void *value, void *data)
return value == data;
}
-static size_t check_name_value_deleted_flag(DICTIONARY *dict, NAME_VALUE *nv, const char *name, const char *value, int refcount, NAME_VALUE_FLAGS deleted_flags, bool searchable, bool browsable, bool linked) {
+static size_t check_name_value_deleted_flag(DICTIONARY *dict, NAME_VALUE *nv, const char *name, const char *value, unsigned refcount, NAME_VALUE_FLAGS deleted_flags, bool searchable, bool browsable, bool linked) {
size_t errors = 0;
fprintf(stderr, "NAME_VALUE name is '%s', expected '%s'...\t\t\t\t", namevalue_get_name(nv), name);
@@ -1995,7 +1998,7 @@ static size_t check_name_value_deleted_flag(DICTIONARY *dict, NAME_VALUE *nv, co
else
fprintf(stderr, "OK\n");
- fprintf(stderr, "NAME_VALUE refcount is %d, expected %d...\t\t\t\t\t", nv->refcount, refcount);
+ fprintf(stderr, "NAME_VALUE refcount is %u, expected %u...\t\t\t\t\t", nv->refcount, refcount);
if (nv->refcount != refcount) {
fprintf(stderr, "FAILED\n");
errors++;
diff --git a/web/api/netdata-swagger.json b/web/api/netdata-swagger.json
index a53f3f0873..25d5103985 100644
--- a/web/api/netdata-swagger.json
+++ b/web/api/netdata-swagger.json
@@ -48,7 +48,7 @@
"/chart": {
"get": {
"summary": "Get info about a specific chart",
- "description": "The Chart endpoint returns detailed information about a chart.",
+ "description": "The chart endpoint returns detailed information about a chart.",
"parameters": [
{
"name": "chart",
@@ -82,6 +82,115 @@
}
}
},
+ "/contexts": {
+ "get": {
+ "summary": "Get a list of all contexts available at the server",
+ "description": "The contexts endpoint returns a summary about all contexts stored in the netdata server.",
+ "parameters": [
+ {
+ "name": "options",
+ "in": "query",
+ "description": "Options that affect data generation.",
+ "required": false,
+ "allowEmptyValue": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "full",
+ "all",
+ "charts",
+ "dimensions",
+ "labels",
+ "queue",
+ "flags",
+ "deleted"
+ ]
+ },
+ "default": [
+ "full"
+ ]
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "An array of contexts.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/context_summary"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/context": {
+ "get": {
+ "summary": "Get info about a specific context",
+ "description": "The context endpoint returns detailed information about a given context.",
+ "parameters": [
+ {
+ "name": "context",
+ "in": "query",
+ "description": "The id of the context as returned by the /contexts call.",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "format": "as returned by /contexts",
+ "default": "system.cpu"
+ }
+ },
+ {
+ "name": "options",
+ "in": "query",
+ "description": "Options that affect data generation.",
+ "required": false,
+ "allowEmptyValue": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "full",
+ "all",
+ "charts",
+ "dimensions",
+ "labels",
+ "queue",
+ "flags",
+ "deleted"
+ ]
+ },
+ "default": [
+ "full"
+ ]
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A javascript object with detailed information about the context.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/context"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "No context id was supplied in the request."
+ },
+ "404": {
+ "description": "No context with the given id is found."
+ }
+ }
+ }
+ },
"/alarm_variables": {
"get": {
"summary": "List variables available to configure alarms for a chart",
@@ -1678,6 +1787,89 @@
}
}
},
+ "context_summary": {
+ "type": "object",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The hostname of the netdata server."
+ },
+ "machine_guid": {
+ "type": "string",
+ "description": "The unique installation id of this netdata server."
+ },
+ "node_id": {
+ "type": "string",
+ "description": "The unique node id of this netdata server at the hub.",
+ "example": "nightly"
+ },
+ "claim_id": {
+ "type": "string",
+ "description": "The unique handshake id of this netdata server and the hub."
+ },
+ "host_labels": {
+ "type": "object",
+ "description": "The host labels associated with this netdata server."
+ },
+ "context": {
+ "type": "object",
+ "description": "An object containing all the context objects available at the netdata server. This is used as an indexed array. The key of each context object is the id of the context.",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/context"
+ }
+ }
+ }
+ },
+ "context": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string",
+ "description": "The version of this context. The number are not sequential, but bigger numbers depict a newer object."
+ },
+ "hub_version": {
+ "type": "string",
+ "description": "The version of this context, as known by hub."
+ },
+ "family": {
+ "type": "string",
+ "description": "The family of the context. When multiple charts of a context have different families, the netdata server replaces the different parts with [x], so that the context can have only one family."
+ },
+ "title": {
+ "type": "string",
+ "description": "The title of the context. When multiple charts of a context have different titles, the netdata server replaces the different parts with [x], so that the context can have only one title."
+ },
+ "priority": {
+ "type": "number",
+ "description": "The relative priority of the context. When multiple contexts have different priorities, the minimum among them is selected as the priority of the context."
+ },
+ "units": {
+ "type": "string",
+ "description": "The unit of measurement for the values of all dimensions of the context. If multple charts of context have different units, the latest collected is selected."
+ },
+ "chart_type": {
+ "type": "string",
+ "description": "The chart type.",
+ "enum": [
+ "line",
+ "area",
+ "stacked"
+ ]
+ },
+ "first_time_t": {
+ "type": "number",
+ "description": "The UNIX timestamp of the first entry (the oldest) in the database."
+ },
+ "last_time_t": {
+ "type": "number",
+ "description": "The UNIX timestamp of the latest entry in the database."
+ },
+ "charts": {
+ "type": "object",
+ "description": "An object containing all the charts available for the chart. This is used as an indexed array. For each pair in the dictionary, the key is the id of the chart and the value provides all details about the chart."
+ }
+ }
+ },
"alarm_variables": {
"type": "object",
"properties": {
diff --git a/web/api/netdata-swagger.yaml b/web/api/netdata-swagger.yaml
index eb9652a3ce..97e24b7383 100644
--- a/web/api/netdata-swagger.yaml
+++ b/web/api/netdata-swagger.yaml
@@ -43,7 +43,7 @@ paths:
/chart:
get:
summary: Get info about a specific chart
- description: The Chart endpoint returns detailed information about a chart.
+ description: The chart endpoint returns detailed information about a chart.
parameters:
- name: chart
in: query
@@ -64,6 +64,83 @@ paths:
description: No chart id was supplied in the request.
"404":
description: No chart with the given id is found.
+ /contexts:
+ get:
+ summary: Get a list of all contexts available at the server
+ description: The contexts endpoint returns a summary about all contexts stored in the
+ netdata server.
+ parameters:
+ - name: options
+ in: query
+ description: Options that affect data generation.
+ required: false
+ allowEmptyValue: true
+ schema:
+ type: array
+ items:
+ type: string
+ enum:
+ - full
+ - all
+ - charts
+ - dimensions
+ - labels
+ - queue
+ - flags
+ - deleted
+ default:
+ - full
+ responses:
+ "200":
+ description: An array of contexts.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/context_summary"
+ /context:
+ get:
+ summary: Get info about a specific context
+ description: The context endpoint returns detailed information about a given context.
+ parameters:
+ - name: context
+ in: query
+ description: The id of the context as returned by the /contexts call.
+ required: true
+ schema:
+ type: string
+ format: as returned by /contexts
+ default: system.cpu
+ - name: options
+ in: query
+ description: Options that affect data generation.
+ required: false
+ allowEmptyValue: true
+ schema:
+ type: array
+ items:
+ type: string
+ enum:
+ - full
+ - all
+ - charts
+ - dimensions
+ - labels
+ - queue
+ - flags
+ - deleted
+ default:
+ - full
+ responses:
+ "200":
+ description: A javascript object with detailed information about the context.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/context"
+ "400":
+ description: No context id was supplied in the request.
+ "404":
+ description: No context with the given id is found.
/alarm_variables:
get:
summary: List variables available to configure alarms for a chart
@@ -1377,6 +1454,67 @@ components:
type: number
nullable: true
description: Chart health red threshold.
+ context_summary:
+ type: object
+ properties:
+ hostname:
+ type: string
+ description: The hostname of the netdata server.
+ machine_guid:
+ type: string
+ description: The unique installation id of this netdata server.
+ node_id:
+ type: string
+ description: The unique node id of this netdata server at the hub.
+ example: nightly
+ claim_id:
+ type: string
+ description: The unique handshake id of this netdata server and the hub.
+ host_labels:
+ type: object
+ description: The host labels associated with this netdata server.
+ context:
+ type: object
+ description: An object containing all the context objects available at the netdata server. This is used as an indexed array. The key of each context object is the id of the context.
+ additionalProperties:
+ $ref: "#/components/schemas/context"
+ context:
+ type: object
+ properties:
+ version:
+ type: string
+ description: The version of this context. The number are not sequential, but bigger numbers depict a newer object.
+ hub_version:
+ type: string
+ description: The version of this context, as known by hub.
+ family:
+ type: string
+ description: The family of the context. When multiple charts of a context have different families, the netdata server replaces the different parts with [x], so that the context can have only one family.
+ title:
+ type: string
+ description: The title of the context. When multiple charts of a context have different titles, the netdata server replaces the different parts with [x], so that the context can have only one title.
+ priority:
+ type: number
+ description: The relative priority of the context. When multiple contexts have different priorities, the minimum among them is selected as the priority of the context.
+ units:
+ type: string
+ description: The unit of measurement for the values of all dimensions of the context. If multple charts of context have different units, the latest collected is selected.
+ chart_type:
+ type: string
+ description: The chart type.
+ enum:
+ - line
+ - area
+ - stacked
+ first_time_t:
+ type: number
+ description: The UNIX timestamp of the first entry (the oldest) in the database.
+ last_time_t:
+ type: number
+ description: The UNIX timestamp of the latest entry in the database.
+ charts:
+ type: object
+ description: An object containing all the charts available for the chart. This is used as an indexed array. For each pair in the dictionary, the key is the id of the chart and the value provides all details about the chart.
alarm_variables:
type: object
properties:
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 7f5c72379d..dcd35b4b8a 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -374,13 +374,84 @@ inline int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_c
return web_client_api_request_single_chart(host, w, url, health_api_v1_chart_variables2json);
}
-int web_client_api_request_v1_contexts(RRDHOST *host, struct web_client *w, char *url) {