diff options
author | Costa Tsaousis (ktsaou) <costa@tsaousis.gr> | 2017-03-01 00:47:50 +0200 |
---|---|---|
committer | Costa Tsaousis (ktsaou) <costa@tsaousis.gr> | 2017-03-01 00:47:50 +0200 |
commit | 73212e3a8731012fee476e373f4a5b647f5126e5 (patch) | |
tree | 126ae28daf56cef4e0d5eee4a28dd238c33fec4f | |
parent | 3f17406218fb82ea4a929354ec26ce9d653b1e94 (diff) |
self-cleaning obsolete cgroups and network interfaces from memory; fixes #1163; fixes #1358
-rwxr-xr-x | CMakeLists.txt | 2 | ||||
-rw-r--r-- | conf.d/health.d/net.conf | 15 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/common.h | 1 | ||||
-rw-r--r-- | src/health.c | 34 | ||||
-rw-r--r-- | src/proc_net_dev.c | 217 | ||||
-rw-r--r-- | src/rrd.h | 13 | ||||
-rw-r--r-- | src/rrd2json.c | 532 | ||||
-rw-r--r-- | src/rrd2json.h | 16 | ||||
-rw-r--r-- | src/rrd2json_api_old.c | 487 | ||||
-rw-r--r-- | src/rrd2json_api_old.h | 14 | ||||
-rw-r--r-- | src/rrdhost.c | 49 | ||||
-rw-r--r-- | src/rrdset.c | 64 | ||||
-rw-r--r-- | src/sys_fs_cgroup.c | 893 | ||||
-rw-r--r-- | src/web_api_old.c | 14 | ||||
-rw-r--r-- | src/web_api_v1.c | 20 |
16 files changed, 1452 insertions, 920 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 979144e06e..8931d8f806 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,7 @@ set(NETDATA_SOURCE_FILES src/web_client.h src/web_server.c src/web_server.h - src/rrdhost.c src/rrdfamily.c src/rrdset.c src/rrddim.c src/health_log.c src/health_config.c src/health_json.c src/rrdcalc.c src/rrdcalctemplate.c src/rrdvar.c src/rrddimvar.c src/rrdsetvar.c src/rrdpush.c src/rrdpush.h src/web_api_old.c src/web_api_old.h src/web_api_v1.c src/web_api_v1.h) + src/rrdhost.c src/rrdfamily.c src/rrdset.c src/rrddim.c src/health_log.c src/health_config.c src/health_json.c src/rrdcalc.c src/rrdcalctemplate.c src/rrdvar.c src/rrddimvar.c src/rrdsetvar.c src/rrdpush.c src/rrdpush.h src/web_api_old.c src/web_api_old.h src/web_api_v1.c src/web_api_v1.h src/rrd2json_api_old.c src/rrd2json_api_old.h) set(APPS_PLUGIN_SOURCE_FILES src/appconfig.c diff --git a/conf.d/health.d/net.conf b/conf.d/health.d/net.conf index cac0bbbfbe..0232395acf 100644 --- a/conf.d/health.d/net.conf +++ b/conf.d/health.d/net.conf @@ -1,18 +1,3 @@ -# ----------------------------------------------------------------------------- -# make sure we collect values for each interface - -template: interface_last_collected_secs - on: net.net -families: * - calc: $now - $last_collected_t - units: seconds ago - every: 10s - warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) - delay: down 5m multiplier 1.5 max 1h - info: number of seconds since the last successful data collection - to: sysadmin - # ----------------------------------------------------------------------------- # dropped packets diff --git a/src/Makefile.am b/src/Makefile.am index a87cd7a8f4..3e6a79c191 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,6 +75,7 @@ netdata_SOURCES = \ rrddimvar.c \ rrdsetvar.c \ rrd2json.c rrd2json.h \ + rrd2json_api_old.c rrd2json_api_old.h \ rrdpush.c rrdpush.h \ storage_number.c storage_number.h \ unit_test.c unit_test.h \ diff --git a/src/common.h b/src/common.h index 3d864f4244..f53cc5571f 100644 --- a/src/common.h +++ b/src/common.h @@ -206,6 +206,7 @@ #include "plugin_tc.h" #include "plugins_d.h" #include "rrd2json.h" +#include "rrd2json_api_old.h" #include "web_client.h" #include "web_server.h" #include "registry.h" diff --git a/src/health.c b/src/health.c index 0c7983ec1b..57210c77b3 100644 --- a/src/health.c +++ b/src/health.c @@ -281,6 +281,16 @@ static inline int rrdcalc_isrunnable(RRDCALC *rc, time_t now, time_t *next_run) return 0; } + if(unlikely(rrdset_flag_check(rc->rrdset, RRDSET_FLAG_OBSOLETE))) { + debug(D_HEALTH, "Health not running alarm '%s.%s'. The chart has been marked as obsolete", rc->chart?rc->chart:"NOCHART", rc->name); + return 0; + } + + if(unlikely(!rrdset_flag_check(rc->rrdset, RRDSET_FLAG_ENABLED))) { + debug(D_HEALTH, "Health not running alarm '%s.%s'. The chart is not enabled", rc->chart?rc->chart:"NOCHART", rc->name); + return 0; + } + if(unlikely(!rc->rrdset->last_collected_time.tv_sec || rc->rrdset->counter_done < 2)) { debug(D_HEALTH, "Health not running alarm '%s.%s'. Chart is not fully collected yet.", rc->chart?rc->chart:"NOCHART", rc->name); return 0; @@ -398,18 +408,18 @@ void *health_main(void *ptr) { /* time_t old_db_timestamp = rc->db_before; */ int value_is_null = 0; - int ret = rrd2value(rc->rrdset - , wb - , &rc->value - , rc->dimensions - , 1 - , rc->after - , rc->before - , rc->group - , rc->options - , &rc->db_after - , &rc->db_before - , &value_is_null + int ret = rrdset2value_api_v1(rc->rrdset + , wb + , &rc->value + , rc->dimensions + , 1 + , rc->after + , rc->before + , rc->group + , rc->options + , &rc->db_after + , &rc->db_before + , &value_is_null ); if(unlikely(ret != 200)) { diff --git a/src/proc_net_dev.c b/src/proc_net_dev.c index 9b94232624..e0de84c70c 100644 --- a/src/proc_net_dev.c +++ b/src/proc_net_dev.c @@ -8,6 +8,7 @@ struct netdev { // flags int configured; int enabled; + int updated; int do_bandwidth; int do_packets; @@ -67,26 +68,70 @@ struct netdev { struct netdev *next; }; -static struct netdev *netdev_root = NULL; +static struct netdev *netdev_root = NULL, *netdev_last_used = NULL; + +static size_t netdev_added = 0, netdev_found = 0; + +static void netdev_free(struct netdev *d) { + if(d->st_bandwidth) rrdset_flag_set(d->st_bandwidth, RRDSET_FLAG_OBSOLETE); + if(d->st_packets) rrdset_flag_set(d->st_packets, RRDSET_FLAG_OBSOLETE); + if(d->st_errors) rrdset_flag_set(d->st_errors, RRDSET_FLAG_OBSOLETE); + if(d->st_drops) rrdset_flag_set(d->st_drops, RRDSET_FLAG_OBSOLETE); + if(d->st_fifo) rrdset_flag_set(d->st_fifo, RRDSET_FLAG_OBSOLETE); + if(d->st_compressed) rrdset_flag_set(d->st_compressed, RRDSET_FLAG_OBSOLETE); + if(d->st_events) rrdset_flag_set(d->st_events, RRDSET_FLAG_OBSOLETE); + + freez(d->name); + freez(d); +} + +static void netdev_cleanup() { + if(likely(netdev_found == netdev_added)) return; + + struct netdev *d = netdev_root, *last = NULL; + while(d) { + if(unlikely(!d->updated)) { + // info("Removing network device '%s', linked after '%s'", d->name, last?last->name:"ROOT"); + + if(netdev_last_used == d) + netdev_last_used = last; + + struct netdev *t = d; + + if(d == netdev_root || !last) + netdev_root = d = d->next; + + else + last->next = d = d->next; + + t->next = NULL; + netdev_free(t); + } + else { + last = d; + d->updated = 0; + d = d->next; + } + } +} static struct netdev *get_netdev(const char *name) { - static struct netdev *last = NULL; struct netdev *d; uint32_t hash = simple_hash(name); // search it, from the last position to the end - for(d = last ; d ; d = d->next) { + for(d = netdev_last_used ; d ; d = d->next) { if(unlikely(hash == d->hash && !strcmp(name, d->name))) { - last = d->next; + netdev_last_used = d->next; return d; } } // search it from the beginning to the last position we used - for(d = netdev_root ; d != last ; d = d->next) { + for(d = netdev_root ; d != netdev_last_used ; d = d->next) { if(unlikely(hash == d->hash && !strcmp(name, d->name))) { - last = d->next; + netdev_last_used = d->next; return d; } } @@ -96,6 +141,7 @@ static struct netdev *get_netdev(const char *name) { d->name = strdupz(name); d->hash = simple_hash(d->name); d->len = strlen(d->name); + netdev_added++; // link it to the end if(netdev_root) { @@ -142,12 +188,16 @@ int do_proc_net_dev(int update_every, usec_t dt) { ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time + netdev_found = 0; + size_t lines = procfile_lines(ff), l; for(l = 2; l < lines ;l++) { // require 17 words on each line if(unlikely(procfile_linewords(ff, l) < 17)) continue; struct netdev *d = get_netdev(procfile_lineword(ff, l, 0)); + d->updated = 1; + netdev_found++; if(unlikely(!d->configured)) { // this is the first time we see this interface @@ -223,19 +273,27 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_bandwidth == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_bandwidth)) { - d->st_bandwidth = rrdset_find_bytype_localhost("net", d->name); - if(!d->st_bandwidth) - d->st_bandwidth = rrdset_create_localhost("net", d->name, NULL, d->name, "net.net", "Bandwidth" - , "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); + d->st_bandwidth = rrdset_create_localhost( + "net" + , d->name + , NULL + , d->name + , "net.net" + , "Bandwidth" + , "kilobits/s" + , 7000 + , update_every + , RRDSET_TYPE_AREA + ); d->rd_rbytes = rrddim_add(d->st_bandwidth, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); d->rd_tbytes = rrddim_add(d->st_bandwidth, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_bandwidth); - rrddim_set_by_pointer(d->st_bandwidth, d->rd_rbytes, d->rbytes); - rrddim_set_by_pointer(d->st_bandwidth, d->rd_tbytes, d->tbytes); + rrddim_set_by_pointer(d->st_bandwidth, d->rd_rbytes, (collected_number)d->rbytes); + rrddim_set_by_pointer(d->st_bandwidth, d->rd_tbytes, (collected_number)d->tbytes); rrdset_done(d->st_bandwidth); } @@ -246,12 +304,20 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_packets == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_packets)) { - d->st_packets = rrdset_find_bytype_localhost("net_packets", d->name); - if(!d->st_packets) - d->st_packets = rrdset_create_localhost("net_packets", d->name, NULL, d->name, "net.packets" - , "Packets", "packets/s", 7001, update_every - , RRDSET_TYPE_LINE); + d->st_packets = rrdset_create_localhost( + "net_packets" + , d->name + , NULL + , d->name + , "net.packets" + , "Packets" + , "packets/s" + , 7001 + , update_every + , RRDSET_TYPE_LINE + ); + rrdset_flag_set(d->st_packets, RRDSET_FLAG_DETAIL); d->rd_rpackets = rrddim_add(d->st_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); @@ -260,9 +326,9 @@ int do_proc_net_dev(int update_every, usec_t dt) { } else rrdset_next(d->st_packets); - rrddim_set_by_pointer(d->st_packets, d->rd_rpackets, d->rpackets); - rrddim_set_by_pointer(d->st_packets, d->rd_tpackets, d->tpackets); - rrddim_set_by_pointer(d->st_packets, d->rd_rmulticast, d->rmulticast); + rrddim_set_by_pointer(d->st_packets, d->rd_rpackets, (collected_number)d->rpackets); + rrddim_set_by_pointer(d->st_packets, d->rd_tpackets, (collected_number)d->tpackets); + rrddim_set_by_pointer(d->st_packets, d->rd_rmulticast, (collected_number)d->rmulticast); rrdset_done(d->st_packets); } @@ -273,12 +339,19 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_errors == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_errors)) { - d->st_errors = rrdset_find_bytype_localhost("net_errors", d->name); - if(!d->st_errors) - d->st_errors = rrdset_create_localhost("net_errors", d->name, NULL, d->name, "net.errors" - , "Interface Errors", "errors/s", 7002, update_every - , RRDSET_TYPE_LINE); + d->st_errors = rrdset_create_localhost( + "net_errors" + , d->name + , NULL + , d->name + , "net.errors" + , "Interface Errors" + , "errors/s" + , 7002 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(d->st_errors, RRDSET_FLAG_DETAIL); @@ -287,8 +360,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { } else rrdset_next(d->st_errors); - rrddim_set_by_pointer(d->st_errors, d->rd_rerrors, d->rerrors); - rrddim_set_by_pointer(d->st_errors, d->rd_terrors, d->terrors); + rrddim_set_by_pointer(d->st_errors, d->rd_rerrors, (collected_number)d->rerrors); + rrddim_set_by_pointer(d->st_errors, d->rd_terrors, (collected_number)d->terrors); rrdset_done(d->st_errors); } @@ -299,12 +372,19 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_drops == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_drops)) { - d->st_drops = rrdset_find_bytype_localhost("net_drops", d->name); - if(!d->st_drops) - d->st_drops = rrdset_create_localhost("net_drops", d->name, NULL, d->name, "net.drops" - , "Interface Drops", "drops/s", 7003, update_every - , RRDSET_TYPE_LINE); + d->st_drops = rrdset_create_localhost( + "net_drops" + , d->name + , NULL + , d->name + , "net.drops" + , "Interface Drops" + , "drops/s" + , 7003 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(d->st_drops, RRDSET_FLAG_DETAIL); @@ -313,8 +393,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { } else rrdset_next(d->st_drops); - rrddim_set_by_pointer(d->st_drops, d->rd_rdrops, d->rdrops); - rrddim_set_by_pointer(d->st_drops, d->rd_tdrops, d->tdrops); + rrddim_set_by_pointer(d->st_drops, d->rd_rdrops, (collected_number)d->rdrops); + rrddim_set_by_pointer(d->st_drops, d->rd_tdrops, (collected_number)d->tdrops); rrdset_done(d->st_drops); } @@ -325,12 +405,19 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_fifo == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_fifo)) { - d->st_fifo = rrdset_find_bytype_localhost("net_fifo", d->name); - if(!d->st_fifo) - d->st_fifo = rrdset_create_localhost("net_fifo", d->name, NULL, d->name, "net.fifo" - , "Interface FIFO Buffer Errors", "errors", 7004, update_every - , RRDSET_TYPE_LINE); + d->st_fifo = rrdset_create_localhost( + "net_fifo" + , d->name + , NULL + , d->name + , "net.fifo" + , "Interface FIFO Buffer Errors" + , "errors" + , 7004 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(d->st_fifo, RRDSET_FLAG_DETAIL); @@ -339,8 +426,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { } else rrdset_next(d->st_fifo); - rrddim_set_by_pointer(d->st_fifo, d->rd_rfifo, d->rfifo); - rrddim_set_by_pointer(d->st_fifo, d->rd_tfifo, d->tfifo); + rrddim_set_by_pointer(d->st_fifo, d->rd_rfifo, (collected_number)d->rfifo); + rrddim_set_by_pointer(d->st_fifo, d->rd_tfifo, (collected_number)d->tfifo); rrdset_done(d->st_fifo); } @@ -351,11 +438,19 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_compressed == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_compressed)) { - d->st_compressed = rrdset_find_bytype_localhost("net_compressed", d->name); - if(!d->st_compressed) - d->st_compressed = rrdset_create_localhost("net_compressed", d->name, NULL, d->name - , "net.compressed", "Compressed Packets", "packets/s" - , 7005, update_every, RRDSET_TYPE_LINE); + + d->st_compressed = rrdset_create_localhost( + "net_compressed" + , d->name + , NULL + , d->name + , "net.compressed" + , "Compressed Packets" + , "packets/s" + , 7005 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(d->st_compressed, RRDSET_FLAG_DETAIL); @@ -364,8 +459,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { } else rrdset_next(d->st_compressed); - rrddim_set_by_pointer(d->st_compressed, d->rd_rcompressed, d->rcompressed); - rrddim_set_by_pointer(d->st_compressed, d->rd_tcompressed, d->tcompressed); + rrddim_set_by_pointer(d->st_compressed, d->rd_rcompressed, (collected_number)d->rcompressed); + rrddim_set_by_pointer(d->st_compressed, d->rd_tcompressed, (collected_number)d->tcompressed); rrdset_done(d->st_compressed); } @@ -376,11 +471,19 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(d->do_events == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_events)) { - d->st_events = rrdset_find_bytype_localhost("net_events", d->name); - if(!d->st_events) - d->st_events = rrdset_create_localhost("net_events", d->name, NULL, d->name, "net.events" - , "Network Interface Events", "events/s", 7006, update_every - , RRDSET_TYPE_LINE); + + d->st_events = rrdset_create_localhost( + "net_events" + , d->name + , NULL + , d->name + , "net.events" + , "Network Interface Events" + , "events/s" + , 7006 + , update_every + , RRDSET_TYPE_LINE + ); rrdset_flag_set(d->st_events, RRDSET_FLAG_DETAIL); @@ -390,12 +493,14 @@ int do_proc_net_dev(int update_every, usec_t dt) { } else rrdset_next(d->st_events); - rrddim_set_by_pointer(d->st_events, d->rd_rframe, d->rframe); - rrddim_set_by_pointer(d->st_events, d->rd_tcollisions, d->tcollisions); - rrddim_set_by_pointer(d->st_events, d->rd_tcarrier, d->tcarrier); + rrddim_set_by_pointer(d->st_events, d->rd_rframe, (collected_number)d->rframe); + rrddim_set_by_pointer(d->st_events, d->rd_tcollisions, (collected_number)d->tcollisions); + rrddim_set_by_pointer(d->st_events, d->rd_tcarrier, (collected_number)d->tcarrier); rrdset_done(d->st_events); } } + netdev_cleanup(); + return 0; } @@ -213,7 +213,8 @@ typedef enum rrdset_flags { RRDSET_FLAG_ENABLED = 1 << 0, // enables or disables a chart RRDSET_FLAG_DETAIL = 1 << 1, // if set, the data set should be considered as a detail of another // (the master data set should be the one that has the same family and is not detail) - RRDSET_FLAG_DEBUG = 1 << 2 // enables or disables debugging for a chart + RRDSET_FLAG_DEBUG = 1 << 2, // enables or disables debugging for a chart + RRDSET_FLAG_OBSOLETE = 1 << 3 // this is marked by the collector/module as obsolete } RRDSET_FLAGS; #define rrdset_flag_check(st, flag) ((st)->flags & flag) @@ -276,7 +277,9 @@ struct rrdset { size_t counter; // the number of times we added values to this database size_t counter_done; // the number of times rrdset_done() has been called - size_t unused[10]; + + time_t last_accessed_time; // the last time this RRDSET has been accessed + size_t unused[9]; uint32_t hash; // a simple hash on the id, to speed up searching // we first compare hashes, and only if the hashes are equal we do string comparisons @@ -540,6 +543,9 @@ extern void rrdset_next_usec(RRDSET *st, usec_t microseconds); extern void rrdset_done(RRDSET *st); +// checks if the RRDSET should be offered to viewers +#define rrdset_is_available_for_viewers(st) (rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && !rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE) && (st)->dimensions) + // get the total duration in seconds of the round robin database #define rrdset_duration(st) ((time_t)( (((st)->counter >= ((unsigned long)(st)->entries))?(unsigned long)(st)->entries:(st)->counter) * (st)->update_every )) @@ -617,6 +623,9 @@ extern void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc); #define rrdset_index_del(host, st) (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index), (avl *)(st)) extern RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st); +extern void rrdset_save(RRDSET *st); +extern void rrdhost_cleanup(RRDHOST *host); + #endif /* NETDATA_RRD_INTERNALS */ diff --git a/src/rrd2json.c b/src/rrd2json.c index 2a46fb1345..ec10e4d577 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -83,6 +83,8 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) size_t c, dimensions = 0, memory = 0, alarms = 0; RRDSET *st; + time_t now = now_realtime_sec(); + buffer_sprintf(wb, "{\n" "\t\"hostname\": \"%s\"" ",\n\t\"version\": \"%s\"" @@ -100,13 +102,15 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) c = 0; rrdhost_rdlock(host); rrdset_foreach_read(st, host) { - if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { + if(rrdset_is_available_for_viewers(st)) { if(c) buffer_strcat(wb, ","); buffer_strcat(wb, "\n\t\t\""); buffer_strcat(wb, st->id); buffer_strcat(wb, "\": "); rrd_stats_api_v1_chart_with_data(st, wb, &dimensions, &memory); + c++; + st->last_accessed_time = now; } } @@ -134,14 +138,15 @@ void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) if(unlikely(rrd_hosts_available > 1)) { rrd_rdlock(); RRDHOST *h; - rrdhost_foreach_read(h) + rrdhost_foreach_read(h) { buffer_sprintf(wb, - "%s\n\t\t{" - "\n\t\t\t\"hostname\": \"%s\"" - "\n\t\t}" - , (h != localhost)?",":"" - , h->hostname + "%s\n\t\t{" + "\n\t\t\t\"hostname\": \"%s\"" + "\n\t\t}" + , (h != localhost) ? "," : "" + , h->hostname ); + } rrd_unlock(); } else { @@ -189,7 +194,7 @@ void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb) { prometheus_name_copy(chart, st->id, PROMETHEUS_ELEMENT_MAX); buffer_strcat(wb, "\n"); - if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { + if(rrdset_is_available_for_viewers(st)) { rrdset_rdlock(st); // for each dimension @@ -261,7 +266,7 @@ void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) { shell_name_copy(chart, st->id, SHELL_ELEMENT_MAX); buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name); - if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { + if(rrdset_is_available_for_viewers(st)) { rrdset_rdlock(st); // for each dimension @@ -319,157 +324,6 @@ void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) { // ---------------------------------------------------------------------------- -unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) -{ - time_t now = now_realtime_sec(); - - rrdset_rdlock(st); - - buffer_sprintf(wb, - "\t\t{\n" - "\t\t\t\"id\": \"%s\",\n" - "\t\t\t\"name\": \"%s\",\n" - "\t\t\t\"type\": \"%s\",\n" - "\t\t\t\"family\": \"%s\",\n" - "\t\t\t\"context\": \"%s\",\n" - "\t\t\t\"title\": \"%s\",\n" - "\t\t\t\"priority\": %ld,\n" - "\t\t\t\"enabled\": %d,\n" - "\t\t\t\"units\": \"%s\",\n" - "\t\t\t\"url\": \"/data/%s/%s\",\n" - "\t\t\t\"chart_type\": \"%s\",\n" - "\t\t\t\"counter\": %lu,\n" - "\t\t\t\"entries\": %ld,\n" - "\t\t\t\"first_entry_t\": %ld,\n" - "\t\t\t\"last_entry\": %lu,\n" - "\t\t\t\"last_entry_t\": %ld,\n" - "\t\t\t\"last_entry_secs_ago\": %ld,\n" - "\t\t\t\"update_every\": %d,\n" - "\t\t\t\"isdetail\": %d,\n" - "\t\t\t\"usec_since_last_update\": %llu,\n" - "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n" - "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n" - "\t\t\t\"dimensions\": [\n" - , st->id - , st->name - , st->type - , st->family - , st->context - , st->title - , st->priority - , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?1:0 - , st->units - , st->name, options?options:"" - , rrdset_type_name(st->chart_type) - , st->counter - , st->entries - , rrdset_first_entry_t(st) - , rrdset_last_slot(st) - , rrdset_last_entry_t(st) - , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st) - , st->update_every - , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?1:0 - , st->usec_since_last_update - , st->collected_total - , st->last_collected_total - ); - - unsigned long memory = st->memsize; - - RRDDIM *rd; - rrddim_foreach_read(rd, st) { - - memory += rd->memsize; - - buffer_sprintf(wb, - "\t\t\t\t{\n" - "\t\t\t\t\t\"id\": \"%s\",\n" - "\t\t\t\t\t\"name\": \"%s\",\n" - "\t\t\t\t\t\"entries\": %ld,\n" - "\t\t\t\t\t\"isHidden\": %d,\n" - "\t\t\t\t\t\"algorithm\": \"%s\",\n" - "\t\t\t\t\t\"multiplier\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"divisor\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"last_entry_t\": %ld,\n" - "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n" - "\t\t\t\t\t\"memory\": %lu\n" - "\t\t\t\t}%s\n" - , rd->id - , rd->name - , rd->entries - , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0 - , rrd_algorithm_name(rd->algorithm) - , rd->multiplier - , rd->divisor - , rd->last_collected_time.tv_sec - , rd->collected_value - , rd->calculated_value - , rd->last_collected_value - , rd->last_calculated_value - , rd->memsize - , rd->next?",":"" - ); - } - - buffer_sprintf(wb, - "\t\t\t],\n" - "\t\t\t\"memory\" : %lu\n" - "\t\t}" - , memory - ); - - rrdset_unlock(st); - return memory; -} - -#define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n" -#define RRD_GRAPH_JSON_FOOTER "\n\t]\n}\n" - -void rrd_stats_graph_json(RRDSET *st, char *options, BUFFER *wb) -{ - buffer_strcat(wb, RRD_GRAPH_JSON_HEADER); - rrd_stats_one_json(st, options, wb); - buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER); -} - -void rrd_stats_all_json(RRDHOST *host, BUFFER *wb) -{ - unsigned long memory = 0; - long c = 0; - RRDSET *st; - - buffer_strcat(wb, RRD_GRAPH_JSON_HEADER); - - rrdhost_rdlock(host); - rrdset_foreach_read(st, host) { - if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { - if(c) buffer_strcat(wb, ",\n"); - memory += rrd_stats_one_json(st, NULL, wb); - c++; - } - } - rrdhost_unlock(host); - - buffer_sprintf(wb, "\n\t],\n" - "\t\"hostname\": \"%s\",\n" - "\t\"update_every\": %d,\n" - "\t\"history\": %d,\n" - "\t\"memory\": %lu\n" - "}\n" - , host->hostname - , host->rrd_update_every - , host->rrd_history_entries - , memory - ); -} - - - -// ---------------------------------------------------------------------------- - // RRDR dimension options #define RRDR_EMPTY 0x01 // the dimension contains / the value is empty (null) #define RRDR_RESET 0x02 // the dimension contains / the value is reset @@ -1665,7 +1519,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g ); r->group = group; - r->update_every = group * st->update_every; + r->update_every = (int)group * st->update_every; r->before = now; r->after = now; @@ -1817,8 +1671,20 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g return r; } -int rrd2value(RRDSET *st, BUFFER *wb, calculate |