0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-05-06 02:00:18 +00:00

Add message queue statistics ()

* Add IPC message queue charts

* Add obsolete flag for dimensions

* Delete obsolete dimensions from memory

* Remove files for obsolete dimensions, filter requests

* Make empty charts obsolete

* Minimize obsolete dimension checks

* Limit the number of dimensions in memory

* Remove obsolete dimensions on netdata exit

* Update documentation

* Move flag to the end

* Fix typo

* Fix typo
This commit is contained in:
Vladimir Kobal 2019-02-11 13:24:24 +02:00 committed by GitHub
parent cbe45897de
commit 2f6f8155db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 431 additions and 167 deletions
backends/prometheus
collectors
daemon/config
database
streaming
web/api
exporters/shell
formatters

View file

@ -291,7 +291,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
// for each dimension
RRDDIM *rd;
rrddim_foreach_read(rd, st) {
if(rd->collections_counter) {
if(rd->collections_counter && !rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
char dimension[PROMETHEUS_ELEMENT_MAX + 1];
char *suffix = "";

View file

@ -55,8 +55,8 @@
#define NETDATA_CHART_PRIO_SYSTEM_ENTROPY 1000
#define NETDATA_CHART_PRIO_SYSTEM_UPTIME 1000
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_QUEUES 990 // freebsd only
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES 1000 // freebsd only
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE 1100 // freebsd only
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES 1000
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE 1100
#define NETDATA_CHART_PRIO_SYSTEM_IPC_SEMAPHORES 1000
#define NETDATA_CHART_PRIO_SYSTEM_IPC_SEM_ARRAYS 1000
#define NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SEGS 1000 // freebsd only

View file

@ -233,7 +233,7 @@ the template is:
the template is:
> DIMENSION id [name [algorithm [multiplier [divisor [hidden]]]]]
> DIMENSION id [name [algorithm [multiplier [divisor [options]]]]]
where:
@ -283,10 +283,9 @@ the template is:
an integer value to divide the collected value,
if empty or missing, `1` is used
- `hidden`
- `options`
giving the keyword `hidden` will make this dimension hidden,
it will take part in the calculations but will not be presented in the chart
a space separated list of options, enclosed in quotes. Options supported: `obsolete` to mark a dimension as obsolete (netdata will delete it after some time) and `hidden` to make this dimension hidden, it will take part in the calculations but will not be presented in the chart.
#### VARIABLE

View file

@ -394,10 +394,17 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN);
rrddim_flag_clear(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
if(options && *options) {
if(strstr(options, "obsolete") != NULL)
rrddim_is_obsolete(st, rd);
else
rrddim_isnot_obsolete(st, rd);
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);
}
else {
rrddim_isnot_obsolete(st, rd);
}
}
else if(likely(hash == VARIABLE_HASH && !strcmp(s, PLUGINSD_KEYWORD_VARIABLE))) {
char *name = words[1];

View file

@ -20,6 +20,7 @@
- `/proc/loadavg` (system load and total processes running)
- `/proc/sys/kernel/random/entropy_avail` (random numbers pool availability - used in cryptography)
- `/sys/class/power_supply` (power supply properties)
- `ipc` (IPC semaphores and message queues)
- `ksm` Kernel Same-Page Merging performance (several files under `/sys/kernel/mm/ksm`).
- `netdata` (internal netdata resources utilization)
@ -343,4 +344,18 @@ corresponding `min` or `empty` attribute, then Netdata will still provide
the corresponding `min` or `empty`, which will then always read as zero.
This way, alerts which match on these will still work.
## IPC
This module monitors the number of semaphores, semaphore arrays, number of messages in message queues, and amount of memory used by message queues. As far as the message queue charts are dynamic, sane limits are applied for the number of dimensions per chart (the limit is configurable).
#### configuration
```
[plugin:proc:ipc]
# semaphore totals = yes
# message queues = yes
# msg filename to monitor = /proc/sysvipc/msg
# max dimensions in memory allowed = 50
```
[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fproc.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]()

View file

@ -53,6 +53,18 @@ union semun {
};
#endif
struct message_queue {
unsigned long long id;
int found;
RRDDIM *rd_messages;
RRDDIM *rd_bytes;
unsigned long long messages;
unsigned long long bytes;
struct message_queue * next;
};
static inline int ipc_sem_get_limits(struct ipc_limits *lim) {
static procfile *ff = NULL;
static int error_shown = 0;
@ -162,31 +174,96 @@ static inline int ipc_sem_get_status(struct ipc_status *st) {
return 0;
}
int ipc_msq_get_info(char *msg_filename, struct message_queue **message_queue_root) {
static procfile *ff;
struct message_queue *msq;
if(unlikely(!ff)) {
ff = procfile_open(config_get("plugin:proc:ipc", "msg filename to monitor", msg_filename), " \t:", PROCFILE_FLAG_DEFAULT);
if(unlikely(!ff)) return 1;
}
ff = procfile_readall(ff);
if(unlikely(!ff)) return 1;
size_t lines = procfile_lines(ff);
size_t words = 0;
if(unlikely(lines < 2)) {
error("Cannot read %s. Expected 2 or more lines, read %zu.", ff->filename, lines);
return 1;
}
// loop through all lines except the first and the last ones
size_t l;
for(l = 1; l < lines - 1; l++) {
words = procfile_linewords(ff, l);
if(unlikely(words < 2)) continue;
if(unlikely(words < 14)) {
error("Cannot read %s line. Expected 14 params, read %zu.", ff->filename, words);
continue;
}
// find the id in the linked list or create a new stucture
int found = 0;
unsigned long long id = str2ull(procfile_lineword(ff, l, 1));
for(msq = *message_queue_root; msq ; msq = msq->next) {
if(unlikely(id == msq->id)) {
found = 1;
break;
}
}
if(unlikely(!found)) {
msq = callocz(1, sizeof(struct message_queue));
msq->next = *message_queue_root;
*message_queue_root = msq;
msq->id = id;
}
msq->messages = str2ull(procfile_lineword(ff, l, 4));
msq->bytes = str2ull(procfile_lineword(ff, l, 3));
msq->found = 1;
}
return 0;
}
int do_ipc(int update_every, usec_t dt) {
(void)dt;
static int initialized = 0, read_limits_next = -1;
static int do_sem = -1, do_msg = -1;
static int read_limits_next = -1;
static struct ipc_limits limits;
static struct ipc_status status;
static RRDVAR *arrays_max = NULL, *semaphores_max = NULL;
static RRDSET *st_semaphores = NULL, *st_arrays = NULL;
static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL;
static char *msg_filename = NULL;
static struct message_queue *message_queue_root = NULL;
static long long dimensions_limit;
if(unlikely(!initialized)) {
initialized = 1;
if(unlikely(do_sem == -1)) {
do_sem = config_get_boolean("plugin:proc:ipc", "semaphore totals", CONFIG_BOOLEAN_YES);
do_msg = config_get_boolean("plugin:proc:ipc", "message queues", CONFIG_BOOLEAN_YES);
char filename[FILENAME_MAX + 1];
snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sysvipc/msg");
msg_filename = config_get("plugin:proc:ipc", "msg filename to monitor", filename);
dimensions_limit = config_get_number("plugin:proc:ipc", "max dimensions in memory allowed", 50);
// make sure it works
if(ipc_sem_get_limits(&limits) == -1) {
error("unable to fetch semaphore limits");
return 1;
do_sem = CONFIG_BOOLEAN_NO;
}
// make sure it works
if(ipc_sem_get_status(&status) == -1) {
else if(ipc_sem_get_status(&status) == -1) {
error("unable to fetch semaphore statistics");
return 1;
do_sem = CONFIG_BOOLEAN_NO;
}
else {
// create the charts
if(unlikely(!st_semaphores)) {
st_semaphores = rrdset_create_localhost(
@ -229,6 +306,18 @@ int do_ipc(int update_every, usec_t dt) {
arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_arrays_max");
}
struct stat stbuf;
if (stat(msg_filename, &stbuf)) {
do_msg = CONFIG_BOOLEAN_NO;
}
if(unlikely(do_sem == CONFIG_BOOLEAN_NO && do_msg == CONFIG_BOOLEAN_NO)) {
error("ipc module disabled");
return 1;
}
}
if(likely(do_sem != CONFIG_BOOLEAN_NO)) {
if(unlikely(read_limits_next < 0)) {
if(unlikely(ipc_sem_get_limits(&limits) == -1)) {
error("Unable to fetch semaphore limits.");
@ -258,6 +347,118 @@ int do_ipc(int update_every, usec_t dt) {
if(st_arrays->counter_done) rrdset_next(st_arrays);
rrddim_set_by_pointer(st_arrays, rd_arrays, status.semusz);
rrdset_done(st_arrays);
}
// --------------------------------------------------------------------
if(likely(do_msg != CONFIG_BOOLEAN_NO)) {
static RRDSET *st_msq_messages = NULL, *st_msq_bytes = NULL;
int ret = ipc_msq_get_info(msg_filename, &message_queue_root);
if(!ret && message_queue_root) {
if(unlikely(!st_msq_messages))
st_msq_messages = rrdset_create_localhost(
"system"
, "message_queue_messages"
, NULL
, "ipc message queues"
, NULL
, "IPC Message Queue Number of Messages"
, "messages"
, PLUGIN_PROC_NAME
, "ipc"
, NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES
, update_every
, RRDSET_TYPE_STACKED
);
else
rrdset_next(st_msq_messages);
if(unlikely(!st_msq_bytes))
st_msq_bytes = rrdset_create_localhost(
"system"
, "message_queue_bytes"
, NULL
, "ipc message queues"
, NULL
, "IPC Message Queue Used Bytes"
, "bytes"
, PLUGIN_PROC_NAME
, "ipc"
, NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE
, update_every
, RRDSET_TYPE_STACKED
);
else
rrdset_next(st_msq_bytes);
struct message_queue *msq = message_queue_root, *msq_prev = NULL;
while(likely(msq)){
if(likely(msq->found)) {
if(unlikely(!msq->rd_messages || !msq->rd_bytes)) {
char id[RRD_ID_LENGTH_MAX + 1];
snprintfz(id, RRD_ID_LENGTH_MAX, "%llu", msq->id);
if(likely(!msq->rd_messages)) msq->rd_messages = rrddim_add(st_msq_messages, id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
if(likely(!msq->rd_bytes)) msq->rd_bytes = rrddim_add(st_msq_bytes, id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
}
rrddim_set_by_pointer(st_msq_messages, msq->rd_messages, msq->messages);
rrddim_set_by_pointer(st_msq_bytes, msq->rd_bytes, msq->bytes);
msq->found = 0;
}
else {
rrddim_is_obsolete(st_msq_messages, msq->rd_messages);
rrddim_is_obsolete(st_msq_bytes, msq->rd_bytes);
// remove message queue from the linked list
if(!msq_prev)
message_queue_root = msq->next;
else
msq_prev->next = msq->next;
freez(msq);
msq = NULL;
}
if(likely(msq)) {
msq_prev = msq;
msq = msq->next;
}
else if(!msq_prev)
msq = message_queue_root;
else
msq = msq_prev->next;
}
rrdset_done(st_msq_messages);
rrdset_done(st_msq_bytes);
long long dimensions_num = 0;
RRDDIM *rd;
rrdset_rdlock(st_msq_messages);
rrddim_foreach_read(rd, st_msq_messages) dimensions_num++;
rrdset_unlock(st_msq_messages);
if(unlikely(dimensions_num > dimensions_limit)) {
info("Message queue statistics has been disabled");
info("There are %lld dimensions in memory but limit was set to %lld", dimensions_num, dimensions_limit);
rrdset_is_obsolete(st_msq_messages);
rrdset_is_obsolete(st_msq_bytes);
st_msq_messages = NULL;
st_msq_bytes = NULL;
do_msg = CONFIG_BOOLEAN_NO;
}
else if(unlikely(!message_queue_root)) {
info("Making chart %s (%s) obsolete since it does not have any dimensions", st_msq_messages->name, st_msq_messages->id);
rrdset_is_obsolete(st_msq_messages);
st_msq_messages = NULL;
info("Making chart %s (%s) obsolete since it does not have any dimensions", st_msq_bytes->name, st_msq_bytes->id);
rrdset_is_obsolete(st_msq_bytes);
st_msq_bytes = NULL;
}
}
}
return 0;
}

View file

@ -69,10 +69,10 @@ errors flood protection period | `1200` | UNUSED - Length of period (in sec) dur
errors to trigger flood protection | `200` | UNUSED - Number of errors written to the log in `errors flood protection period` sec before flood protection is activated.
run as user | `netdata` | The user netdata will run as.
pthread stack size | auto-detected |
cleanup obsolete charts after seconds | `3600` | See [monitoring ephemeral containers](../../collectors/cgroups.plugin/#monitoring-ephemeral-containers)
cleanup obsolete charts after seconds | `3600` | See [monitoring ephemeral containers](../../collectors/cgroups.plugin/#monitoring-ephemeral-containers), also sets the timeout for cleaning up obsolete dimensions
gap when lost iterations above | `1` |
cleanup orphan hosts after seconds | `3600` | How long to wait until automatically removing from the DB a remote netdata host (slave) that is no longer sending data.
delete obsolete charts files | `yes` | See [monitoring ephemeral containers](../../collectors/cgroups.plugin/#monitoring-ephemeral-containers)
delete obsolete charts files | `yes` | See [monitoring ephemeral containers](../../collectors/cgroups.plugin/#monitoring-ephemeral-containers), also affects the deletion of files for obsolete dimensions
delete orphan hosts files | `yes` | Set to `no` to disable non-responsive host removal.
### [web] section options

View file

@ -31,6 +31,7 @@ typedef struct alarm_entry ALARM_ENTRY;
extern int default_rrd_update_every;
extern int default_rrd_history_entries;
extern int gap_when_lost_iterations_above;
extern time_t rrdset_free_obsolete_time;
#define RRD_ID_LENGTH_MAX 200
@ -123,7 +124,8 @@ typedef struct rrdfamily RRDFAMILY;
typedef enum rrddim_flags {
RRDDIM_FLAG_NONE = 0,
RRDDIM_FLAG_HIDDEN = (1 << 0), // this dimension will not be offered to callers
RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = (1 << 1) // do not offer RESET or OVERFLOW info to callers
RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = (1 << 1), // do not offer RESET or OVERFLOW info to callers
RRDDIM_FLAG_OBSOLETE = (1 << 2) // this is marked by the collector/module as obsolete
} RRDDIM_FLAGS;
#ifdef HAVE_C___ATOMIC
@ -257,6 +259,7 @@ typedef enum rrdset_flags {
RRDSET_FLAG_HOMEGENEOUS_CHECK = 1 << 11, // if set, the chart should be checked to determine if the dimensions as homogeneous
RRDSET_FLAG_HIDDEN = 1 << 12, // if set, do not show this chart on the dashboard, but use it for backends
RRDSET_FLAG_SYNC_CLOCK = 1 << 13, // if set, microseconds on next data collection will be ignored (the chart will be synced to now)
RRDSET_FLAG_OBSOLETE_DIMENSIONS = 1 << 14 // this is marked by the collector/module when a chart has obsolete dimensions
} RRDSET_FLAGS;
#ifdef HAVE_C___ATOMIC
@ -846,6 +849,9 @@ extern RRDDIM *rrddim_find(RRDSET *st, const char *id);
extern int rrddim_hide(RRDSET *st, const char *id);
extern int rrddim_unhide(RRDSET *st, const char *id);
extern void rrddim_is_obsolete(RRDSET *st, RRDDIM *rd);
extern void rrddim_isnot_obsolete(RRDSET *st, RRDDIM *rd);
extern collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value);
extern collected_number rrddim_set(RRDSET *st, const char *id, collected_number value);
@ -879,6 +885,7 @@ extern void rrdset_free(RRDSET *st);
extern void rrdset_reset(RRDSET *st);
extern void rrdset_save(RRDSET *st);
extern void rrdset_delete(RRDSET *st);
extern void rrdset_delete_obsolete_dimensions(RRDSET *st);
extern void rrdhost_cleanup_obsolete_charts(RRDHOST *host);

View file

@ -368,6 +368,18 @@ int rrddim_unhide(RRDSET *st, const char *id) {
return 0;
}
inline void rrddim_is_obsolete(RRDSET *st, RRDDIM *rd) {
debug(D_RRD_CALLS, "rrddim_is_obsolete() for chart %s, dimension %s", st->name, rd->name);
rrddim_flag_set(rd, RRDDIM_FLAG_OBSOLETE);
rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE_DIMENSIONS);
}
inline void rrddim_isnot_obsolete(RRDSET *st, RRDDIM *rd) {
debug(D_RRD_CALLS, "rrddim_isnot_obsolete() for chart %s, dimension %s", st->name, rd->name);
rrddim_flag_clear(rd, RRDDIM_FLAG_OBSOLETE);
}
// ----------------------------------------------------------------------------
// RRDDIM - collect values for a dimension

View file

@ -665,6 +665,8 @@ void rrdhost_cleanup_charts(RRDHOST *host) {
if(rrdhost_delete_obsolete_charts && rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE))
rrdset_delete(st);
else if(rrdhost_delete_obsolete_charts && rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE_DIMENSIONS))
rrdset_delete_obsolete_dimensions(st);
else
rrdset_save(st);

View file

@ -417,6 +417,24 @@ void rrdset_delete(RRDSET *st) {
recursively_delete_dir(st->cache_dir, "left-over chart");
}
void rrdset_delete_obsolete_dimensions(RRDSET *st) {
RRDDIM *rd;
rrdset_check_rdlock(st);
info("Deleting dimensions of chart '%s' ('%s') from disk...", st->id, st->name);
rrddim_foreach_read(rd, st) {
if(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || rd->rrd_memory_mode == RRD_MEMORY_MODE_MAP)) {
info("Deleting dimension file '%s'.", rd->cache_filename);
if(unlikely(unlink(rd->cache_filename) == -1))
error("Cannot delete dimension file '%s'", rd->cache_filename);
}
}
}
}
// ----------------------------------------------------------------------------
// RRDSET - create a chart
@ -1303,6 +1321,11 @@ void rrdset_done(RRDSET *st) {
continue;
}
if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE))) {
error("Dimension %s in chart '%s' has the OBSOLETE flag set, but it is collected.", rd->name, st->id);
rrddim_isnot_obsolete(st, rd);
}
#ifdef NETDATA_INTERNAL_CHECKS
rrdset_debug(st, "%s: START "
" last_collected_value = " COLLECTED_NUMBER_FORMAT
@ -1582,37 +1605,37 @@ void rrdset_done(RRDSET *st) {
// ALL DONE ABOUT THE DATA UPDATE
// --------------------------------------------------------------------
/*
// find if there are any obsolete dimensions (not updated recently)
if(unlikely(rrd_delete_unupdated_dimensions)) {
// find if there are any obsolete dimensions
time_t now = now_realtime_sec();
for( rd = st->dimensions; likely(rd) ; rd = rd->next )
if((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)
if(unlikely(rrddim_flag_check(st, RRDSET_FLAG_OBSOLETE_DIMENSIONS))) {
rrddim_foreach_read(rd, st)
if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)))
break;
if(unlikely(rd)) {
RRDDIM *last;
// there is dimension to free
// there is a dimension to free
// upgrade our read lock to a write lock
rrdset_unlock(st);
rrdset_wrlock(st);
for( rd = st->dimensions, last = NULL ; likely(rd) ; ) {
// remove it only it is not updated in rrd_delete_unupdated_dimensions seconds
if(unlikely((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)) {
if(unlikely(rd->last_collected_time.tv_sec + rrdset_free_obsolete_time < now)) {
info("Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id);
if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || rd->rrd_memory_mode == RRD_MEMORY_MODE_MAP)) {
info("Deleting dimension file '%s'.", rd->cache_filename);
if(unlikely(unlink(rd->cache_filename) == -1))
error("Cannot delete dimension file '%s'", rd->cache_filename);
}
if(unlikely(!last)) {
st->dimensions = rd->next;
rd->next = NULL;
rrddim_free(st, rd);
rd = st->dimensions;
continue;
}
else {
last->next = rd->next;
rd->next = NULL;
rrddim_free(st, rd);
rd = last->next;
continue;
@ -1622,14 +1645,11 @@ void rrdset_done(RRDSET *st) {
last = rd;
rd = rd->next;
}
if(unlikely(!st->dimensions)) {
info("Disabling chart %s (%s) since it does not have any dimensions", st->name, st->id);
st->enabled = 0;
}
else {
rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE_DIMENSIONS);
}
}
}
*/
rrdset_unlock(st);

View file

@ -188,12 +188,13 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
rrddim_foreach_read(rd, st) {
buffer_sprintf(
host->rrdpush_sender_buffer
, "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s\"\n"
, "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s %s\"\n"
, rd->id
, rd->name
, rrd_algorithm_name(rd->algorithm)
, rd->multiplier
, rd->divisor
, rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)?"obsolete":""
, rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?"hidden":""
, rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)?"noreset":""
);

View file

@ -39,7 +39,7 @@ void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) {
// for each dimension
RRDDIM *rd;
rrddim_foreach_read(rd, st) {
if(rd->collections_counter) {
if(rd->collections_counter && !rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
char dimension[SHELL_ELEMENT_MAX + 1];
shell_name_copy(dimension, rd->name?rd->name:rd->id, SHELL_ELEMENT_MAX);
@ -126,7 +126,7 @@ void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) {
// for each dimension
RRDDIM *rd;
rrddim_foreach_read(rd, st) {
if(rd->collections_counter) {
if(rd->collections_counter && !rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
buffer_sprintf(wb, "%s\n"
"\t\t\t\"%s\": {\n"

View file

@ -51,7 +51,7 @@ void rrdset2json(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memor
size_t dimensions = 0;
RRDDIM *rd;
rrddim_foreach_read(rd, st) {
if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) continue;
if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN) || rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) continue;
memory += rd->memsize;