272 lines
9.3 KiB
C
Executable File
272 lines
9.3 KiB
C
Executable File
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
#define NETDATA_RRD_INTERNALS
|
|
|
|
#include "metadatalog.h"
|
|
#include "metalogpluginsd.h"
|
|
|
|
PARSER_RC metalog_pluginsd_host_action(
|
|
void *user, char *machine_guid, char *hostname, char *registry_hostname, int update_every, char *os, char *timezone,
|
|
char *tags)
|
|
{
|
|
struct metalog_pluginsd_state *state = ((PARSER_USER_OBJECT *)user)->private;
|
|
|
|
RRDHOST *host = rrdhost_find_by_guid(machine_guid, 0);
|
|
if (host)
|
|
goto write_replay;
|
|
|
|
if (strcmp(machine_guid, registry_get_this_machine_guid()) == 0) {
|
|
struct metalog_record record;
|
|
struct metadata_logfile *metalogfile = state->metalogfile;
|
|
|
|
uuid_parse(machine_guid, record.uuid);
|
|
mlf_record_insert(metalogfile, &record);
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
// Ignore HOST command for now
|
|
// TODO: Remove when the next task is completed ie. accept new children in the lcoalhost / multidb
|
|
return PARSER_RC_OK;
|
|
|
|
host = rrdhost_create(
|
|
hostname
|
|
, registry_hostname
|
|
, machine_guid
|
|
, os
|
|
, timezone
|
|
, tags
|
|
, NULL
|
|
, NULL
|
|
, update_every
|
|
, 3600
|
|
, RRD_MEMORY_MODE_DBENGINE
|
|
, 0 // health enabled
|
|
, 0 // Push enabled
|
|
, NULL
|
|
, NULL
|
|
, NULL
|
|
, callocz(1, sizeof(struct rrdhost_system_info))
|
|
, 0 // localhost
|
|
, 1 // archived
|
|
);
|
|
|
|
write_replay:
|
|
if (host) { /* It's a valid object */
|
|
struct metalog_record record;
|
|
struct metadata_logfile *metalogfile = state->metalogfile;
|
|
|
|
uuid_copy(record.uuid, host->host_uuid);
|
|
mlf_record_insert(metalogfile, &record);
|
|
}
|
|
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
PARSER_RC metalog_pluginsd_chart_action(void *user, char *type, char *id, char *name, char *family, char *context,
|
|
char *title, char *units, char *plugin, char *module, int priority,
|
|
int update_every, RRDSET_TYPE chart_type, char *options)
|
|
{
|
|
struct metalog_pluginsd_state *state = ((PARSER_USER_OBJECT *)user)->private;
|
|
RRDSET *st = NULL;
|
|
RRDHOST *host = ((PARSER_USER_OBJECT *) user)->host;
|
|
uuid_t *chart_uuid;
|
|
|
|
chart_uuid = uuid_is_null(state->uuid) ? NULL : &state->uuid;
|
|
st = rrdset_create_custom(
|
|
host, type, id, name, family, context, title, units,
|
|
plugin, module, priority, update_every,
|
|
chart_type, RRD_MEMORY_MODE_DBENGINE, (host)->rrd_history_entries, 1, chart_uuid);
|
|
|
|
rrdset_isnot_obsolete(st); /* archived charts cannot be obsolete */
|
|
if (options && *options) {
|
|
if (strstr(options, "detail"))
|
|
rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
|
|
else
|
|
rrdset_flag_clear(st, RRDSET_FLAG_DETAIL);
|
|
|
|
if (strstr(options, "hidden"))
|
|
rrdset_flag_set(st, RRDSET_FLAG_HIDDEN);
|
|
else
|
|
rrdset_flag_clear(st, RRDSET_FLAG_HIDDEN);
|
|
|
|
if (strstr(options, "store_first"))
|
|
rrdset_flag_set(st, RRDSET_FLAG_STORE_FIRST);
|
|
else
|
|
rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
|
|
} else {
|
|
rrdset_flag_clear(st, RRDSET_FLAG_DETAIL);
|
|
rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
|
|
}
|
|
((PARSER_USER_OBJECT *)user)->st = st;
|
|
|
|
if (chart_uuid) { /* It's a valid object */
|
|
struct metalog_record record;
|
|
struct metadata_logfile *metalogfile = state->metalogfile;
|
|
|
|
uuid_copy(record.uuid, state->uuid);
|
|
mlf_record_insert(metalogfile, &record);
|
|
uuid_clear(state->uuid); /* Consume UUID */
|
|
}
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
PARSER_RC metalog_pluginsd_dimension_action(void *user, RRDSET *st, char *id, char *name, char *algorithm,
|
|
long multiplier, long divisor, char *options, RRD_ALGORITHM algorithm_type)
|
|
{
|
|
struct metalog_pluginsd_state *state = ((PARSER_USER_OBJECT *)user)->private;
|
|
UNUSED(user);
|
|
UNUSED(algorithm);
|
|
uuid_t *dim_uuid;
|
|
|
|
dim_uuid = uuid_is_null(state->uuid) ? NULL : &state->uuid;
|
|
|
|
RRDDIM *rd = rrddim_add_custom(st, id, name, multiplier, divisor, algorithm_type, RRD_MEMORY_MODE_DBENGINE, 1,
|
|
dim_uuid);
|
|
rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN);
|
|
rrddim_flag_clear(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
|
|
rrddim_isnot_obsolete(st, rd); /* archived dimensions cannot be obsolete */
|
|
if (options && *options) {
|
|
if (strstr(options, "hidden") != NULL)
|
|
rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN);
|
|
if (strstr(options, "noreset") != NULL)
|
|
rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
|
|
if (strstr(options, "nooverflow") != NULL)
|
|
rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
|
|
}
|
|
if (dim_uuid) { /* It's a valid object */
|
|
struct metalog_record record;
|
|
struct metadata_logfile *metalogfile = state->metalogfile;
|
|
|
|
uuid_copy(record.uuid, state->uuid);
|
|
mlf_record_insert(metalogfile, &record);
|
|
uuid_clear(state->uuid); /* Consume UUID */
|
|
}
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
PARSER_RC metalog_pluginsd_guid_action(void *user, uuid_t *uuid)
|
|
{
|
|
struct metalog_pluginsd_state *state = ((PARSER_USER_OBJECT *)user)->private;
|
|
|
|
uuid_copy(state->uuid, *uuid);
|
|
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
PARSER_RC metalog_pluginsd_context_action(void *user, uuid_t *uuid)
|
|
{
|
|
GUID_TYPE ret;
|
|
struct metalog_pluginsd_state *state = ((PARSER_USER_OBJECT *)user)->private;
|
|
struct metalog_instance *ctx = state->ctx;
|
|
char object[49], chart_object[33], id_str[1024];
|
|
uuid_t *chart_guid, *chart_char_guid;
|
|
RRDHOST *host;
|
|
|
|
ret = find_object_by_guid(uuid, object, 49);
|
|
switch (ret) {
|
|
case GUID_TYPE_NOTFOUND:
|
|
if (unlikely(ctx->rrdeng_ctx->host && uuid_compare(ctx->rrdeng_ctx->host->host_uuid, *uuid)))
|
|
error_with_guid(uuid, "Failed to find valid context");
|
|
break;
|
|
case GUID_TYPE_CHAR:
|
|
error_with_guid(uuid, "Ignoring unexpected type GUID_TYPE_CHAR");
|
|
break;
|
|
case GUID_TYPE_CHART:
|
|
case GUID_TYPE_DIMENSION:
|
|
host = ctx->rrdeng_ctx->host;
|
|
switch (ret) {
|
|
case GUID_TYPE_CHART:
|
|
chart_char_guid = (uuid_t *)(object + 16);
|
|
|
|
ret = find_object_by_guid(chart_char_guid, id_str, RRD_ID_LENGTH_MAX + 1);
|
|
if (unlikely(GUID_TYPE_CHAR != ret))
|
|
error_with_guid(uuid, "Failed to find valid chart name");
|
|
else
|
|
((PARSER_USER_OBJECT *)user)->st = rrdset_find(host, id_str);
|
|
break;
|
|
case GUID_TYPE_DIMENSION:
|
|
chart_guid = (uuid_t *)(object + 16);
|
|
|
|
ret = find_object_by_guid(chart_guid, chart_object, 33);
|
|
if (unlikely(GUID_TYPE_CHART != ret)) {
|
|
error_with_guid(uuid, "Failed to find valid chart");
|
|
break;
|
|
}
|
|
chart_char_guid = (uuid_t *)(object + 16);
|
|
|
|
ret = find_object_by_guid(chart_char_guid, id_str, RRD_ID_LENGTH_MAX + 1);
|
|
if (unlikely(GUID_TYPE_CHAR != ret))
|
|
error_with_guid(uuid, "Failed to find valid chart name");
|
|
else
|
|
((PARSER_USER_OBJECT *)user)->st = rrdset_find(host, id_str);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case GUID_TYPE_HOST:
|
|
/* Ignore for now */
|
|
break;
|
|
case GUID_TYPE_NOSPACE:
|
|
error_with_guid(uuid, "Not enough space for object retrieval");
|
|
break;
|
|
default:
|
|
error("Unknown return code %u from find_object_by_guid", ret);
|
|
break;
|
|
}
|
|
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
PARSER_RC metalog_pluginsd_tombstone_action(void *user, uuid_t *uuid)
|
|
{
|
|
GUID_TYPE ret;
|
|
struct metalog_pluginsd_state *state = ((PARSER_USER_OBJECT *)user)->private;
|
|
struct metalog_instance *ctx = state->ctx;
|
|
RRDHOST *host = ctx->rrdeng_ctx->host;
|
|
RRDSET *st;
|
|
RRDDIM *rd;
|
|
|
|
ret = find_object_by_guid(uuid, NULL, 0);
|
|
switch (ret) {
|
|
case GUID_TYPE_CHAR:
|
|
fatal_assert(0);
|
|
break;
|
|
case GUID_TYPE_CHART:
|
|
st = metalog_get_chart_from_uuid(ctx, uuid);
|
|
if (st) {
|
|
rrdhost_wrlock(host);
|
|
rrdset_free(st);
|
|
rrdhost_unlock(host);
|
|
} else {
|
|
debug(D_METADATALOG, "Ignoring nonexistent chart metadata record.");
|
|
}
|
|
break;
|
|
case GUID_TYPE_DIMENSION:
|
|
rd = metalog_get_dimension_from_uuid(ctx, uuid);
|
|
if (rd) {
|
|
st = rd->rrdset;
|
|
rrdset_wrlock(st);
|
|
rrddim_free_custom(st, rd, 0);
|
|
rrdset_unlock(st);
|
|
}
|
|
else {
|
|
debug(D_METADATALOG, "Ignoring nonexistent dimension metadata record.");
|
|
}
|
|
break;
|
|
case GUID_TYPE_HOST:
|
|
/* Ignore for now */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return PARSER_RC_OK;
|
|
}
|
|
|
|
void metalog_pluginsd_state_init(struct metalog_pluginsd_state *state, struct metalog_instance *ctx)
|
|
{
|
|
state->ctx = ctx;
|
|
state->skip_record = 0;
|
|
uuid_clear(state->uuid);
|
|
state->metalogfile = NULL;
|
|
} |