summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--CMakeLists.txt34
-rw-r--r--Makefile.am15
-rw-r--r--collectors/README.md1
-rw-r--r--collectors/apps.plugin/apps_groups.conf1
-rw-r--r--collectors/plugins.d/README.md1
-rw-r--r--collectors/xenstat.plugin/Makefile.am8
-rw-r--r--collectors/xenstat.plugin/README.md45
-rw-r--r--collectors/xenstat.plugin/xenstat_plugin.c1196
-rw-r--r--configure.ac106
-rw-r--r--docs/Add-more-charts-to-netdata.md14
-rwxr-xr-xdocs/generator/buildyaml.sh1
-rwxr-xr-xnetdata-installer.sh17
-rw-r--r--web/gui/dashboard_info.js12
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
+ , vbd
+ , NETDATA_CHART_PRIO_XENSTAT_DOMAIN_VBD_REQUESTS + vbd
+ , netdata_update_every
+ , obsolet