diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 34 | ||||
-rw-r--r-- | Makefile.am | 15 | ||||
-rw-r--r-- | collectors/README.md | 1 | ||||
-rw-r--r-- | collectors/apps.plugin/apps_groups.conf | 1 | ||||
-rw-r--r-- | collectors/plugins.d/README.md | 1 | ||||
-rw-r--r-- | collectors/xenstat.plugin/Makefile.am | 8 | ||||
-rw-r--r-- | collectors/xenstat.plugin/README.md | 45 | ||||
-rw-r--r-- | collectors/xenstat.plugin/xenstat_plugin.c | 1196 | ||||
-rw-r--r-- | configure.ac | 106 | ||||
-rw-r--r-- | docs/Add-more-charts-to-netdata.md | 14 | ||||
-rwxr-xr-x | docs/generator/buildyaml.sh | 1 | ||||
-rwxr-xr-x | netdata-installer.sh | 17 | ||||
-rw-r--r-- | web/gui/dashboard_info.js | 12 |
14 files changed, 1438 insertions, 16 deletions
diff --git a/.gitignore b/.gitignore index 2ee0f8f25d..60a9f79f37 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,9 @@ cups.plugin nfacct.plugin !nfacct.plugin/ +xenstat.plugin +!xenstat.plugin/ + cgroup-network !cgroup-network/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 127369cb4a..46a3fed32f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,16 @@ pkg_check_modules(NFACCT libnetfilter_acct) # ----------------------------------------------------------------------------- +# Detect libxenstat + +pkg_check_modules(XENSTAT libxenstat) +# later we use: +# ${XENSTAT_LIBRARIES} +# ${XENSTAT_CFLAGS_OTHER} +# ${XENSTAT_INCLUDE_DIRS} + + +# ----------------------------------------------------------------------------- # Detect MacOS IOKit/Foundation framework IF(MACOS) @@ -250,6 +260,10 @@ set(NFACCT_PLUGIN_FILES collectors/nfacct.plugin/plugin_nfacct.c ) +set(XENSTAT_PLUGIN_FILES + collectors/xenstat.plugin/xenstat_plugin.c + ) + set(PROC_PLUGIN_FILES collectors/proc.plugin/ipc.c collectors/proc.plugin/plugin_proc.c @@ -520,6 +534,12 @@ ELSE() SET(ENABLE_PLUGIN_NFACCT False) ENDIF() +IF(XENSTAT_LIBRARIES) + SET(ENABLE_PLUGIN_XENSTAT True) +ELSE() + SET(ENABLE_PLUGIN_XENSTAT False) +ENDIF() + # ----------------------------------------------------------------------------- # apps.plugin @@ -564,6 +584,20 @@ ENDIF() # ----------------------------------------------------------------------------- +# xenstat.plugin + +IF(ENABLE_PLUGIN_XENSTAT) + message(STATUS "xenstat.plugin: enabled") + add_executable(xenstat.plugin config.h ${XENSTAT_PLUGIN_FILES}) + target_link_libraries (xenstat.plugin libnetdata ${NETDATA_COMMON_LIBRARIES} ${XENSTAT_LIBRARIES}) + target_include_directories(xenstat.plugin PUBLIC ${NETDATA_COMMON_INCLUDE_DIRS} ${XENSTAT_INCLUDE_DIRS}) + target_compile_options(xenstat.plugin PUBLIC ${NETDATA_COMMON_CFLAGS} ${XENSTAT_CFLAGS_OTHER}) +ELSE() + message(STATUS "xenstat.plugin: disabled (requires libxenstat)") +ENDIF() + + +# ----------------------------------------------------------------------------- # cgroup-network IF(ENABLE_PLUGIN_CGROUP_NETWORK) diff --git a/Makefile.am b/Makefile.am index 33aa01a877..c64072c41f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -109,6 +109,7 @@ AM_CFLAGS = \ $(OPTIONAL_LIBCAP_LIBS) \ $(OPTIONAL_IPMIMONITORING_CFLAGS) \ $(OPTIONAL_CUPS_CFLAGS) \ + $(OPTIONAL_XENSTAT_CFLAGS) \ $(NULL) sbin_PROGRAMS = @@ -226,6 +227,11 @@ NFACCT_PLUGIN_FILES = \ $(LIBNETDATA_FILES) \ $(NULL) +XENSTAT_PLUGIN_FILES = \ + collectors/xenstat.plugin/xenstat_plugin.c \ + $(LIBNETDATA_FILES) \ + $(NULL) + PROC_PLUGIN_FILES = \ collectors/proc.plugin/ipc.c \ collectors/proc.plugin/plugin_proc.c \ @@ -513,3 +519,12 @@ if ENABLE_PLUGIN_NFACCT $(OPTIONAL_NFACCT_LIBS) \ $(NULL) endif + +if ENABLE_PLUGIN_XENSTAT + plugins_PROGRAMS += xenstat.plugin + xenstat_plugin_SOURCES = $(XENSTAT_PLUGIN_FILES) + xenstat_plugin_LDADD = \ + $(NETDATA_COMMON_LIBS) \ + $(OPTIONAL_XENSTAT_LIBS) \ + $(NULL) +endif diff --git a/collectors/README.md b/collectors/README.md index 81efe19b71..86c2a9fd24 100644 --- a/collectors/README.md +++ b/collectors/README.md @@ -35,6 +35,7 @@ plugin|lang|O/S|runs as|modular|description [idlejitter.plugin](idlejitter.plugin/)|`C`|any|internal|-|measures CPU latency and jitter on all operating systems [macos.plugin](macos.plugin/)|`C`|macos|internal|yes|collects resource usage and performance data on MacOS systems [nfacct.plugin](nfacct.plugin/)|`C`|linux|external|-|collects netfilter firewall, connection tracker and accounting metrics using `libmnl` and `libnetfilter_acct` +[xenstat.plugin](xenstat.plugin/)|`C`|linux|external|-|collects XenServer and XCP-ng metrics using `libxenstat` [node.d.plugin](node.d.plugin/)|`node.js`|any|external|yes|a **plugin orchestrator** for data collection modules written in `node.js`. [plugins.d](plugins.d/)|`C`|any|internal|-|implements the **external plugins** API and serves external plugins [proc.plugin](proc.plugin/)|`C`|linux|internal|yes|collects resource usage and performance data on Linux systems diff --git a/collectors/apps.plugin/apps_groups.conf b/collectors/apps.plugin/apps_groups.conf index 32722fbfa4..da71043298 100644 --- a/collectors/apps.plugin/apps_groups.conf +++ b/collectors/apps.plugin/apps_groups.conf @@ -76,6 +76,7 @@ apps.plugin: apps.plugin freeipmi.plugin: freeipmi.plugin nfacct.plugin: nfacct.plugin cups.plugin: cups.plugin +xenstat.plugin: xenstat.plugin charts.d.plugin: *charts.d.plugin* node.d.plugin: *node.d.plugin* python.d.plugin: *python.d.plugin* diff --git a/collectors/plugins.d/README.md b/collectors/plugins.d/README.md index 2631ec4a09..d5b9b85ef8 100644 --- a/collectors/plugins.d/README.md +++ b/collectors/plugins.d/README.md @@ -13,6 +13,7 @@ plugin|language|O/S|description [fping.plugin](../fping.plugin/)|`C`|all|measures network latency, jitter and packet loss between the monitored node and any number of remote network end points. [freeipmi.plugin](../freeipmi.plugin/)|`C`|linux|collects metrics from enterprise hardware sensors, on Linux servers. [nfacct.plugin](../nfacct.plugin/)|`C`|linux|collects netfilter firewall, connection tracker and accounting metrics using `libmnl` and `libnetfilter_acct`. +[xenstat.plugin](../xenstat.plugin/)|`C`|linux|collects XenServer and XCP-ng metrics using `lxenstat`. [node.d.plugin](../node.d.plugin/)|`node.js`|all|a **plugin orchestrator** for data collection modules written in `node.js`. [python.d.plugin](../python.d.plugin/)|`python`|all|a **plugin orchestrator** for data collection modules written in `python` v2 or v3 (both are supported). diff --git a/collectors/xenstat.plugin/Makefile.am b/collectors/xenstat.plugin/Makefile.am new file mode 100644 index 0000000000..19554bed8e --- /dev/null +++ b/collectors/xenstat.plugin/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/collectors/xenstat.plugin/README.md b/collectors/xenstat.plugin/README.md new file mode 100644 index 0000000000..f803dbf36c --- /dev/null +++ b/collectors/xenstat.plugin/README.md @@ -0,0 +1,45 @@ +# xenstat.plugin + +`xenstat.plugin` collects XenServer and XCP-ng statistics. + +## Prerequisites + +1. install `xen-dom0-libs-devel` and `yajl-devel` using the package manager of your system. + +2. re-install netdata from source. The installer will detect that the required libraries are now available and will also build xenstat.plugin. + +Keep in mind that `libxenstat` requires root access, so the plugin is setuid to root. + +## Charts + +The plugin provides XenServer and XCP-ng host and domains statistics: + +Host: +1. Number of domains. + +Domain: +1. CPU. +2. Memory. +3. Networks. +4. VBDs. + +## Configuration + +If you need to disable xenstat for netdata, edit /etc/netdata/netdata.conf and set: + +``` +[plugins] + xenstat = no +``` + +## Debugging + +You can run the plugin by hand: + +``` +sudo /usr/libexec/netdata/plugins.d/xenstat.plugin 1 debug +``` + +You will get verbose output on what the plugin does. + +[![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%2Fnfacct.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/collectors/xenstat.plugin/xenstat_plugin.c b/collectors/xenstat.plugin/xenstat_plugin.c new file mode 100644 index 0000000000..873b818041 --- /dev/null +++ b/collectors/xenstat.plugin/xenstat_plugin.c @@ -0,0 +1,1196 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../../libnetdata/libnetdata.h" + +#define PLUGIN_XENSTAT_NAME "xenstat.plugin" + +#define NETDATA_CHART_PRIO_XENSTAT_NODE_CPUS 30001 +#define NETDATA_CHART_PRIO_XENSTAT_NODE_CPU_FREQ 30002 +#define NETDATA_CHART_PRIO_XENSTAT_NODE_MEM 30003 +#define NETDATA_CHART_PRIO_XENSTAT_NODE_TMEM 30004 +#define NETDATA_CHART_PRIO_XENSTAT_NODE_DOMAINS 30005 + +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_STATES 30101 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_CPU 30102 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VCPU 30103 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_MEM 30104 + +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_TMEM_PAGES 30104 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_TMEM_OPERATIONS 30105 + +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VBD_OO_REQ 30200 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VBD_REQUESTS 30300 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VBD_SECTORS 30400 + +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_NET_BYTES 30500 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_NET_PACKETS 30600 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_NET_ERRORS 30700 +#define NETDATA_CHART_PRIO_XENSTAT_DOMAIN_NET_DROPS 30800 + +#define TYPE_LENGTH_MAX 200 + +#define CHART_IS_OBSOLETE 1 +#define CHART_IS_NOT_OBSOLETE 0 + +// callback required by fatal() +void netdata_cleanup_and_exit(int ret) { + exit(ret); +} + +void send_statistics( const char *action, const char *action_result, const char *action_data) { + (void) action; + (void) action_result; + (void) action_data; + return; +} + +// callbacks required by popen() +void signals_block(void) {}; +void signals_unblock(void) {}; +void signals_reset(void) {}; + +// callback required by eval() +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) { + (void)variable; + (void)hash; + (void)rc; + (void)result; + return 0; +}; + +// required by get_system_cpus() +char *netdata_configured_host_prefix = ""; + +// Variables + +static int debug = 0; + +static int netdata_update_every = 1; + +#ifdef HAVE_LIBXENSTAT +#include <xenstat.h> +#include <libxl.h> + +struct vcpu_metrics { + unsigned int id; + + unsigned int online; + unsigned long long ns; + + int chart_generated; + int updated; + + struct vcpu_metrics *next; +}; + +struct tmem_metrics { + unsigned long long curr_eph_pages; + unsigned long long succ_eph_gets; + unsigned long long succ_pers_puts; + unsigned long long succ_pers_gets; + + int pages_chart_generated; + int operation_chart_generated; +}; + +struct vbd_metrics { + unsigned int id; + + unsigned int error; + unsigned long long oo_reqs; + unsigned long long rd_reqs; + unsigned long long wr_reqs; + unsigned long long rd_sects; + unsigned long long wr_sects; + + int oo_req_chart_generated; + int requests_chart_generated; + int sectors_chart_generated; + int updated; + + struct vbd_metrics *next; +}; + +struct network_metrics { + unsigned int id; + + unsigned long long rbytes; + unsigned long long rpackets; + unsigned long long rerrs; + unsigned long long rdrops; + + unsigned long long tbytes; + unsigned long long tpackets; + unsigned long long terrs; + unsigned long long tdrops; + + int bytes_chart_generated; + int packets_chart_generated; + int errors_chart_generated; + int drops_chart_generated; + int updated; + + struct network_metrics *next; +}; + +struct domain_metrics { + char *uuid; + uint32_t hash; + + unsigned int id; + char *name; + + // states + unsigned int running; + unsigned int blocked; + unsigned int paused; + unsigned int shutdown; + unsigned int crashed; + unsigned int dying; + + unsigned long long cpu_ns; + unsigned long long cur_mem; + unsigned long long max_mem; + + struct tmem_metrics tmem; + struct vcpu_metrics *vcpu_root; + struct vbd_metrics *vbd_root; + struct network_metrics *network_root; + + int states_chart_generated; + int cpu_chart_generated; + int vcpu_chart_generated; + int num_vcpus_changed; + int mem_chart_generated; + int updated; + + struct domain_metrics *next; +}; + +struct node_metrics{ + unsigned long long tot_mem; + unsigned long long free_mem; + long freeable_mb; + int num_domains; + unsigned int num_cpus; + unsigned long long node_cpu_hz; + + struct domain_metrics *domain_root; +}; + +static struct node_metrics node_metrics = { + .domain_root = NULL +}; + +static inline struct domain_metrics *domain_metrics_get(const char *uuid, uint32_t hash) { + struct domain_metrics *d = NULL, *last = NULL; + for(d = node_metrics.domain_root; d ; last = d, d = d->next) { + if(unlikely(d->hash == hash && !strcmp(d->uuid, uuid))) + return d; + } + + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: allocating memory for domain with uuid %s\n", uuid); + + d = callocz(1, sizeof(struct domain_metrics)); + d->uuid = strdupz(uuid); + d->hash = hash; + + if(unlikely(!last)) { + d->next = node_metrics.domain_root; + node_metrics.domain_root = d; + } + else { + d->next = last->next; + last->next = d; + } + + return d; +} + +static struct domain_metrics *domain_metrics_free(struct domain_metrics *d) { + struct domain_metrics *cur = NULL, *last = NULL; + struct vcpu_metrics *vcpu, *vcpu_f; + struct vbd_metrics *vbd, *vbd_f; + struct network_metrics *network, *network_f; + + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: freeing memory for domain '%s' id %d, uuid %s\n", d->name, d->id, d->uuid); + + for(cur = node_metrics.domain_root; cur ; last = cur, cur = cur->next) { + if(unlikely(cur->hash == d->hash && !strcmp(cur->uuid, d->uuid))) break; + } + + if(unlikely(!cur)) { + error("XENSTAT: failed to free domain metrics."); + return NULL; + } + + if(likely(last)) + last->next = cur->next; + else + node_metrics.domain_root = NULL; + + freez(cur->uuid); + freez(cur->name); + + vcpu = cur->vcpu_root; + while(vcpu) { + vcpu_f = vcpu; + vcpu = vcpu->next; + freez(vcpu_f); + } + + vbd = cur->vbd_root; + while(vbd) { + vbd_f = vbd; + vbd = vbd->next; + freez(vbd_f); + } + + network = cur->network_root; + while(network) { + network_f = network; + network = network->next; + freez(network_f); + } + + freez(cur); + + return last ? last : NULL; +} + +static int vcpu_metrics_collect(struct domain_metrics *d, xenstat_domain *domain) { + static unsigned int last_num_vcpus = 0; + unsigned int num_vcpus = 0; + xenstat_vcpu *vcpu = NULL; + struct vcpu_metrics *vcpu_m = NULL, *last_vcpu_m = NULL; + + num_vcpus = xenstat_domain_num_vcpus(domain); + if(unlikely(num_vcpus != last_num_vcpus)) { + d->num_vcpus_changed = 1; + last_num_vcpus = num_vcpus; + } + + for(vcpu_m = d->vcpu_root; vcpu_m ; vcpu_m = vcpu_m->next) + vcpu_m->updated = 0; + + vcpu_m = d->vcpu_root; + + unsigned int i; + for(i = 0; i < num_vcpus; i++) { + if(unlikely(!vcpu_m)) { + vcpu_m = callocz(1, sizeof(struct vcpu_metrics)); + + if(unlikely(i == 0)) d->vcpu_root = vcpu_m; + else last_vcpu_m->next = vcpu_m; + } + + vcpu_m->id = i; + + vcpu = xenstat_domain_vcpu(domain, i); + + if(unlikely(!vcpu)) { + error("XENSTAT: cannot get VCPU statistics."); + return 1; + } + + vcpu_m->online = xenstat_vcpu_online(vcpu); + vcpu_m->ns = xenstat_vcpu_ns(vcpu); + + vcpu_m->updated = 1; + + last_vcpu_m = vcpu_m; + vcpu_m = vcpu_m->next; + } + + return 0; +} + +static int vbd_metrics_collect(struct domain_metrics *d, xenstat_domain *domain) { + unsigned int num_vbds = xenstat_domain_num_vbds(domain); + xenstat_vbd *vbd = NULL; + struct vbd_metrics *vbd_m = NULL, *last_vbd_m = NULL; + + for(vbd_m = d->vbd_root; vbd_m ; vbd_m = vbd_m->next) + vbd_m->updated = 0; + + vbd_m = d->vbd_root; + + unsigned int i; + for(i = 0; i < num_vbds; i++) { + if(unlikely(!vbd_m)) { + vbd_m = callocz(1, sizeof(struct vbd_metrics)); + + if(unlikely(i == 0)) d->vbd_root = vbd_m; + else last_vbd_m->next = vbd_m; + } + + vbd_m->id = i; + + vbd = xenstat_domain_vbd(domain, i); + + if(unlikely(!vbd)) { + error("XENSTAT: cannot get VBD statistics."); + return 1; + } + + vbd_m->error = xenstat_vbd_error(vbd); + vbd_m->oo_reqs = xenstat_vbd_oo_reqs(vbd); + vbd_m->rd_reqs = xenstat_vbd_rd_reqs(vbd); + vbd_m->wr_reqs = xenstat_vbd_wr_reqs(vbd); + vbd_m->rd_sects = xenstat_vbd_rd_sects(vbd); + vbd_m->wr_sects = xenstat_vbd_wr_sects(vbd); + + vbd_m->updated = 1; + + last_vbd_m = vbd_m; + vbd_m = vbd_m->next; + } + + return 0; +} + +static int network_metrics_collect(struct domain_metrics *d, xenstat_domain *domain) { + unsigned int num_networks = xenstat_domain_num_networks(domain); + xenstat_network *network = NULL; + struct network_metrics *network_m = NULL, *last_network_m = NULL; + + for(network_m = d->network_root; network_m ; network_m = network_m->next) + network_m->updated = 0; + + network_m = d->network_root; + + unsigned int i; + for(i = 0; i < num_networks; i++) { + if(unlikely(!network_m)) { + network_m = callocz(1, sizeof(struct network_metrics)); + + if(unlikely(i == 0)) d->network_root = network_m; + else last_network_m->next = network_m; + } + + network_m->id = i; + + network = xenstat_domain_network(domain, i); + + if(unlikely(!network)) { + error("XENSTAT: cannot get network statistics."); + return 1; + } + + network_m->rbytes = xenstat_network_rbytes(network); + network_m->rpackets = xenstat_network_rpackets(network); + network_m->rerrs = xenstat_network_rerrs(network); + network_m->rdrops = xenstat_network_rdrop(network); + + network_m->tbytes = xenstat_network_tbytes(network); + network_m->tpackets = xenstat_network_tpackets(network); + network_m->terrs = xenstat_network_terrs(network); + network_m->tdrops = xenstat_network_tdrop(network); + + network_m->updated = 1; + + last_network_m = network_m; + network_m = network_m->next; + } + + return 0; +} + +static int xenstat_collect(xenstat_handle *xhandle, libxl_ctx *ctx, libxl_dominfo *info) { + + // mark all old metrics as not-updated + struct domain_metrics *d; + for(d = node_metrics.domain_root; d ; d = d->next) + d->updated = 0; + + xenstat_node *node = xenstat_get_node(xhandle, XENSTAT_ALL); + if (unlikely(!node)) { + error("XENSTAT: failed to retrieve statistics from libxenstat."); + return 1; + } + + node_metrics.tot_mem = xenstat_node_tot_mem(node); + node_metrics.free_mem = xenstat_node_free_mem(node); + node_metrics.freeable_mb = xenstat_node_freeable_mb(node); + node_metrics.num_domains = xenstat_node_num_domains(node); + node_metrics.num_cpus = xenstat_node_num_cpus(node); + node_metrics.node_cpu_hz = xenstat_node_cpu_hz(node); + + int i; + for(i = 0; i < node_metrics.num_domains; i++) { + xenstat_domain *domain = NULL; + char uuid[LIBXL_UUID_FMTLEN + 1]; + + domain = xenstat_node_domain_by_index(node, i); + + // get domain UUID + unsigned int id = xenstat_domain_id(domain); + if(unlikely(libxl_domain_info(ctx, info, id))) { + error("XENSTAT: cannot get domain info."); + } + else { + snprintfz(uuid, LIBXL_UUID_FMTLEN, LIBXL_UUID_FMT "\n", LIBXL_UUID_BYTES(info->uuid)); + } + + uint32_t hash = simple_hash(uuid); + d = domain_metrics_get(uuid, hash); + + d->id = id; + if(unlikely(!d->name)) { + d->name = strdupz(xenstat_domain_name(domain)); + netdata_fix_chart_id(d->name); + if(unlikely(debug)) fprintf(stderr, "xenstat.plugin: domain id %d, uuid %s has name '%s'\n", d->id, d->uuid, d->name); + } + + d->running = xenstat_domain_running(domain); + d->blocked = xenstat_domain_blocked(domain); + d->paused = xenstat_domain_paused(domain); + d->shutdown = xenstat_domain_shutdown(domain); + d->crashed = xenstat_domain_crashed(domain); + d->dying = xenstat_domain_dying(domain); + + d->cpu_ns = xenstat_domain_cpu_ns(domain); + d->cur_mem = xenstat_domain_cur_mem(domain); + d->max_mem = xenstat_domain_max_mem(domain); + + xenstat_tmem *tmem = xenstat_domain_tmem(domain); + d->tmem.curr_eph_pages = xenstat_tmem_curr_eph_pages(tmem); + d->tmem.succ_eph_gets = xenstat_tmem_succ_eph_gets(tmem); + d->tmem.succ_pers_puts = xenstat_tmem_succ_pers_puts(tmem); + d->tmem.succ_pers_gets = xenstat_tmem_succ_pers_gets(tmem); + + if(unlikely(vcpu_metrics_collect(d, domain) || vbd_metrics_collect(d, domain) || network_metrics_collect(d, domain))) { + xenstat_free_node(node); + return 1; + } + + d->updated = 1; + } + + xenstat_free_node(node); + + return 0; +} + +static void xenstat_send_node_metrics() { + static int mem_chart_generated = 0, tmem_chart_generated = 0, domains_chart_generated = 0, cpus_chart_generated = 0, cpu_freq_chart_generated = 0; + + // ---------------------------------------------------------------- + + if(unlikely(!mem_chart_generated)) { + printf("CHART xenstat.mem '' 'Memory Usage' 'MiB' 'memory' '' stacked %d %d '' %s\n" + , NETDATA_CHART_PRIO_XENSTAT_NODE_MEM + , netdata_update_every + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION %s '' absolute 1 %d\n", "free", netdata_update_every * 1024 * 1024); + printf("DIMENSION %s '' absolute 1 %d\n", "used", netdata_update_every * 1024 * 1024); + mem_chart_generated = 1; + } + + printf( + "BEGIN xenstat.mem\n" + "SET free = %lld\n" + "SET used = %lld\n" + "END\n" + , (collected_number) node_metrics.free_mem + , (collected_number) (node_metrics.tot_mem - node_metrics.free_mem) + ); + + // ---------------------------------------------------------------- + + if(unlikely(!tmem_chart_generated)) { + printf("CHART xenstat.tmem '' 'Freeable Transcedent Memory' 'MiB' 'memory' '' line %d %d '' %s\n" + , NETDATA_CHART_PRIO_XENSTAT_NODE_TMEM + , netdata_update_every + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION %s '' absolute 1 %d\n", "freeable", netdata_update_every * 1024 * 1024); + tmem_chart_generated = 1; + } + + printf( + "BEGIN xenstat.tmem\n" + "SET freeable = %lld\n" + "END\n" + , (collected_number) node_metrics.freeable_mb + ); + + // ---------------------------------------------------------------- + + if(unlikely(!domains_chart_generated)) { + printf("CHART xenstat.domains '' 'Number of Domains' 'domains' 'domains' '' line %d %d '' %s\n" + , NETDATA_CHART_PRIO_XENSTAT_NODE_DOMAINS + , netdata_update_every + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION %s '' absolute 1 %d\n", "domains", netdata_update_every); + domains_chart_generated = 1; + } + + printf( + "BEGIN xenstat.domains\n" + "SET domains = %lld\n" + "END\n" + , (collected_number) node_metrics.num_domains + ); + + // ---------------------------------------------------------------- + + if(unlikely(!cpus_chart_generated)) { + printf("CHART xenstat.cpus '' 'Number of CPUs' 'cpus' 'cpu' '' line %d %d '' %s\n" + , NETDATA_CHART_PRIO_XENSTAT_NODE_CPUS + , netdata_update_every + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION %s '' absolute 1 %d\n", "cpus", netdata_update_every); + cpus_chart_generated = 1; + } + + printf( + "BEGIN xenstat.cpus\n" + "SET cpus = %lld\n" + "END\n" + , (collected_number) node_metrics.num_cpus + ); + + // ---------------------------------------------------------------- + + if(unlikely(!cpu_freq_chart_generated)) { + printf("CHART xenstat.cpu_freq '' 'CPU Frequency' 'MHz' 'cpu' '' line %d %d '' %s\n" + , NETDATA_CHART_PRIO_XENSTAT_NODE_CPU_FREQ + , netdata_update_every + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION %s '' absolute 1 %d\n", "frequency", netdata_update_every * 1024 * 1024); + cpu_freq_chart_generated = 1; + } + + printf( + "BEGIN xenstat.cpu_freq\n" + "SET frequency = %lld\n" + "END\n" + , (collected_number) node_metrics.node_cpu_hz + ); +} + +static void print_domain_states_chart_definition(char *type, int obsolete_flag) { + printf("CHART %s.states '' 'Domain States' 'boolean' 'states' 'xendomain.states' line %d %d %s %s\n" + , type + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_STATES + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION running '' absolute 1 %d\n", netdata_update_every); + printf("DIMENSION blocked '' absolute 1 %d\n", netdata_update_every); + printf("DIMENSION paused '' absolute 1 %d\n", netdata_update_every); + printf("DIMENSION shutdown '' absolute 1 %d\n", netdata_update_every); + printf("DIMENSION crashed '' absolute 1 %d\n", netdata_update_every); + printf("DIMENSION dying '' absolute 1 %d\n", netdata_update_every); +} + +static void print_domain_cpu_chart_definition(char *type, int obsolete_flag) { + printf("CHART %s.cpu '' 'CPU Usage (100%% = 1 core)' 'percentage' 'cpu' 'xendomain.cpu' line %d %d %s %s\n" + , type + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_CPU + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION used '' incremental 100 %d\n", netdata_update_every * 1000000000); +} + +static void print_domain_mem_chart_definition(char *type, int obsolete_flag) { + printf("CHART %s.mem '' 'Memory Reservation' 'MiB' 'memory' 'xendomain.mem' line %d %d %s %s\n" + , type + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_MEM + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION maximum '' absolute 1 %d\n", netdata_update_every * 1024 * 1024); + printf("DIMENSION current '' absolute 1 %d\n", netdata_update_every * 1024 * 1024); +} + +static void print_domain_tmem_pages_chart_definition(char *type, int obsolete_flag) { + printf("CHART %s.tmem_pages '' 'Current Number of Transcedent Memory Ephemeral Pages' 'pages' 'memory' 'xendomain.tmem_pages' line %d %d %s %s\n" + , type + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_TMEM_PAGES + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION pages '' absolute 1 %d\n", netdata_update_every); +} + +static void print_domain_tmem_operations_chart_definition(char *type, int obsolete_flag) { + printf("CHART %s.tmem_operations '' 'Successful Transcedent Memory Puts and Gets' 'events/s' 'memory' 'xendomain.tmem_operations' line %d %d %s %s\n" + , type + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_TMEM_OPERATIONS + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION ephemeral_gets 'ephemeral gets' incremental 1 %d\n", netdata_update_every); + printf("DIMENSION persistent_puts 'persistent puts' incremental 1 %d\n", netdata_update_every); + printf("DIMENSION persistent_gets 'persistent gets' incremental 1 %d\n", netdata_update_every); +} + +static void print_domain_vcpu_chart_definition(char *type, struct domain_metrics *d, int obsolete_flag) { + struct vcpu_metrics *vcpu_m; + + printf("CHART %s.vcpu '' 'CPU Usage per VCPU' 'percentage' 'cpu' 'xendomain.vcpu' line %d %d %s %s\n" + , type + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VCPU + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + + for(vcpu_m = d->vcpu_root; vcpu_m; vcpu_m = vcpu_m->next) { + if(likely(vcpu_m->updated && vcpu_m->online)) { + printf("DIMENSION vcpu%u '' incremental 100 %d\n", vcpu_m->id, netdata_update_every * 1000000000); + } + } +} + +static void print_domain_vbd_oo_chart_definition(char *type, unsigned int vbd, int obsolete_flag) { + printf("CHART %s.oo_req_vbd%u '' 'VBD%u \"Out Of\" Requests' 'requests/s' 'vbd' 'xendomain.oo_req_vbd' line %d %d %s %s\n" + , type + , vbd + , vbd + , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VBD_OO_REQ + vbd + , netdata_update_every + , obsolete_flag ? "obsolete": "''" + , PLUGIN_XENSTAT_NAME + ); + printf("DIMENSION requests '' incremental 1 %d\n", netdata_update_every); +} + +static void print_domain_vbd_requests_chart_definition(char *type, unsigned int vbd, int obsolete_flag) { + printf("CHART %s.requests_vbd%u '' 'VBD%u Requests' 'requests/s' 'vbd' 'xendomain.requests_vbd' line %d %d %s %s\n" + , type + , vbd |