diff --git a/0014-api-add-get-container-metrics-api.patch b/0014-api-add-get-container-metrics-api.patch new file mode 100644 index 0000000000000000000000000000000000000000..73b3e4ca31dbe33cd0ed003dc13f11110455cafd --- /dev/null +++ b/0014-api-add-get-container-metrics-api.patch @@ -0,0 +1,266 @@ +From d1f9a992190921783337b71103d3525c3381bedf Mon Sep 17 00:00:00 2001 +From: lifeng68 +Date: Tue, 15 Dec 2020 17:30:01 +0800 +Subject: [PATCH 14/14] api: add get container metrics api + +Signed-off-by: lifeng68 +--- + src/lxc/lxccontainer.c | 174 +++++++++++++++++++++++++++++++++++++++++ + src/lxc/lxccontainer.h | 42 ++++++++++ + 2 files changed, 216 insertions(+) + +diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c +index cbb67f321..9202b73ff 100644 +--- a/src/lxc/lxccontainer.c ++++ b/src/lxc/lxccontainer.c +@@ -5752,6 +5752,179 @@ static bool do_lxcapi_set_start_timeout(struct lxc_container *c, unsigned int s + + WRAP_API_1(bool, lxcapi_set_start_timeout, unsigned int) + ++static uint64_t metrics_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item) ++{ ++ char buf[80] = {0}; ++ int len = 0; ++ uint64_t val = 0; ++ ++ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf), c->name, c->config_path); ++ if (len <= 0) { ++ DEBUG("unable to read cgroup item %s", item); ++ return 0; ++ } ++ ++ val = strtoull(buf, NULL, 0); ++ return val; ++} ++ ++static inline bool is_blk_metrics_read(const char *value) ++{ ++ return strcmp(value, "Read") == 0; ++} ++ ++static inline bool is_blk_metrics_write(const char *value) ++{ ++ return strcmp(value, "Write") == 0; ++} ++ ++static inline bool is_blk_metrics_total(const char *value) ++{ ++ return strcmp(value, "Total") == 0; ++} ++ ++static void metrics_get_blk_stats(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, struct lxc_blkio_metrics *stats) ++{ ++#define BUFSIZE 4096 ++ char buf[BUFSIZE] = {0}; ++ int i = 0; ++ int len = 0; ++ char **lines = NULL; ++ char **cols = NULL; ++ ++ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf), c->name, c->config_path); ++ if (len <= 0) { ++ DEBUG("unable to read cgroup item %s", item); ++ return; ++ } ++ ++ lines = lxc_string_split_and_trim(buf, '\n'); ++ if (lines == NULL) { ++ return; ++ } ++ ++ (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics)); ++ ++ for (i = 0; lines[i]; i++) { ++ cols = lxc_string_split_and_trim(lines[i], ' '); ++ if (cols == NULL) { ++ goto err_out; ++ } ++ if (is_blk_metrics_read(cols[1])) { ++ stats->read += strtoull(cols[2], NULL, 0); ++ } else if (is_blk_metrics_write(cols[1])) { ++ stats->write += strtoull(cols[2], NULL, 0); ++ } ++ if (is_blk_metrics_total(cols[0])) { ++ stats->total = strtoull(cols[1], NULL, 0); ++ } ++ ++ lxc_free_array((void **)cols, free); ++ } ++err_out: ++ lxc_free_array((void **)lines, free); ++ return; ++} ++ ++static uint64_t metrics_match_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, const char *match, int column) ++{ ++#define BUFSIZE 4096 ++ char buf[BUFSIZE] = {0}; ++ int i = 0; ++ int j = 0; ++ int len = 0; ++ uint64_t val = 0; ++ char **lines = NULL; ++ char **cols = NULL; ++ size_t matchlen = 0; ++ ++ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf), c->name, c->config_path); ++ if (len <= 0) { ++ DEBUG("unable to read cgroup item %s", item); ++ goto err_out; ++ } ++ ++ lines = lxc_string_split_and_trim(buf, '\n'); ++ if (lines == NULL) { ++ goto err_out; ++ } ++ ++ matchlen = strlen(match); ++ for (i = 0; lines[i]; i++) { ++ if (strncmp(lines[i], match, matchlen) != 0) { ++ continue; ++ } ++ ++ cols = lxc_string_split_and_trim(lines[i], ' '); ++ if (cols == NULL) { ++ goto err1; ++ } ++ for (j = 0; cols[j]; j++) { ++ if (j == column) { ++ val = strtoull(cols[j], NULL, 0); ++ break; ++ } ++ } ++ lxc_free_array((void **)cols, free); ++ break; ++ } ++err1: ++ lxc_free_array((void **)lines, free); ++err_out: ++ return val; ++} ++ ++/* isulad add get container metrics */ ++static bool do_lxcapi_get_container_metrics(struct lxc_container *c, struct lxc_container_metrics *metrics) ++{ ++ call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL; ++ const char *state = NULL; ++ if (c == NULL || c->lxc_conf == NULL || metrics == NULL) { ++ return false; ++ } ++ ++ state = c->state(c); ++ metrics->state = state; ++ ++ if (!is_stopped(c)) { ++ metrics->init = c->init_pid(c); ++ } else { ++ metrics->init = -1; ++ } ++ ++ cgroup_ops = cgroup_init(c->lxc_conf); ++ if (cgroup_ops == NULL) { ++ return false; ++ } ++ ++ metrics->cpu_use_nanos = metrics_get_ull(c, cgroup_ops, "cpuacct.usage"); ++ metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current"); ++ ++ metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "user", 1); ++ metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "system", 1); ++ ++ // Try to read CFQ stats available on all CFQ enabled kernels first ++ metrics_get_blk_stats(c, cgroup_ops, "blkio.io_serviced_recursive", &metrics->io_serviced); ++ if (metrics->io_serviced.read == 0 && metrics->io_serviced.write == 0 && metrics->io_serviced.total == 0) { ++ metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_service_bytes", &metrics->io_service_bytes); ++ metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_serviced", &metrics->io_serviced); ++ } else { ++ metrics_get_blk_stats(c, cgroup_ops, "blkio.io_service_bytes_recursive", &metrics->io_service_bytes); ++ } ++ ++ metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.usage_in_bytes"); ++ metrics->mem_limit = metrics_get_ull(c, cgroup_ops, "memory.limit_in_bytes"); ++ metrics->kmem_used = metrics_get_ull(c, cgroup_ops, "memory.kmem.usage_in_bytes"); ++ metrics->kmem_limit = metrics_get_ull(c, cgroup_ops, "memory.kmem.limit_in_bytes"); ++ ++ metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "cache", 1); ++ metrics->cache_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_cache", 1); ++ ++ return true; ++} ++ ++WRAP_API_1(bool, lxcapi_get_container_metrics, struct lxc_container_metrics *) ++ + #endif + + #ifdef HAVE_ISULAD +@@ -5924,6 +6097,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath + c->clean_container_resource = lxcapi_clean_container_resource; + c->get_container_pids = lxcapi_get_container_pids; + c->set_start_timeout = lxcapi_set_start_timeout; ++ c->get_container_metrics = lxcapi_get_container_metrics; + #endif + return c; + +diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h +index 2951ac7b4..e30bf6161 100644 +--- a/src/lxc/lxccontainer.h ++++ b/src/lxc/lxccontainer.h +@@ -40,6 +40,37 @@ struct lxc_mount { + int version; + }; + ++struct lxc_blkio_metrics { ++ uint64_t read; ++ uint64_t write; ++ uint64_t total; ++}; ++ ++struct lxc_container_metrics { ++ /* State of container */ ++ const char *state; ++ /* The process ID of the init container */ ++ pid_t init; ++ /* Current pids */ ++ uint64_t pids_current; ++ /* CPU usage */ ++ uint64_t cpu_use_nanos; ++ uint64_t cpu_use_user; ++ uint64_t cpu_use_sys; ++ /* BlkIO usage */ ++ struct lxc_blkio_metrics io_service_bytes; ++ struct lxc_blkio_metrics io_serviced; ++ /* Memory usage */ ++ uint64_t mem_used; ++ uint64_t mem_limit; ++ /* Kernel Memory usage */ ++ uint64_t kmem_used; ++ uint64_t kmem_limit; ++ /* Cache usage */ ++ uint64_t cache; ++ uint64_t cache_total; ++}; ++ + /*! + * An LXC container. + * +@@ -976,6 +1007,17 @@ struct lxc_container { + * \return \c true on success, else \c false. + */ + bool (*set_start_timeout)(struct lxc_container *c, unsigned int start_timeout); ++ ++ /*! isulad add ++ * \brief An API call to set start timeout ++ * ++ * \param c Container. ++ * \param start_timeout Value of start timeout. ++ * ++ * \return \c true on success, else \c false. ++ */ ++ bool (*get_container_metrics)(struct lxc_container *c, struct lxc_container_metrics *metrics); ++ + }; + + /*! +-- +2.25.1 + diff --git a/lxc.spec b/lxc.spec index 924fecec0d0fdf6d1b91c0831afa155255200268..bef5e758565243e93364aa39f0475ba24a933a29 100644 --- a/lxc.spec +++ b/lxc.spec @@ -1,4 +1,4 @@ -%global _release 2020120701 +%global _release 2020121501 Name: lxc Version: 4.0.3 @@ -21,6 +21,7 @@ Patch0010: 0010-cgfsng-adjust-log-level-from-error-to-warn.patch Patch0011: 0011-rootfs-add-make-private-for-root.path-parent.patch Patch0012: 0012-mount-make-possible-to-bind-mount-proc-and-sys-fs.patch Patch0013: 0013-use-path-based-unix-domain-sockets-instead-of-abstra.patch +Patch0014: 0014-api-add-get-container-metrics-api.patch BuildRequires: systemd-units git libtool graphviz docbook2X doxygen chrpath BuildRequires: pkgconfig(libseccomp) @@ -192,6 +193,12 @@ make check %{_mandir}/*/man7/%{name}* %changelog +* Tue Dec 15 2020 lifeng - 4.0.3-2020121501 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC: add get container metrics api to get the stat + * Mon Dec 07 2020 wujing - 4.0.3-2020120701 - Type:enhancement - ID:NA