"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/libglusterfs/src/monitoring.c" (16 Sep 2020, 8761 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "monitoring.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2017 Red Hat, Inc. <http://www.redhat.com>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #include "glusterfs/monitoring.h"
   12 #include "glusterfs/xlator.h"
   13 #include "glusterfs/syscall.h"
   14 
   15 #include <stdlib.h>
   16 
   17 static void
   18 dump_mem_acct_details(xlator_t *xl, int fd)
   19 {
   20     struct mem_acct_rec *mem_rec;
   21     int i = 0;
   22 
   23     if (!xl || !xl->mem_acct || (xl->ctx->active != xl->graph))
   24         return;
   25 
   26     dprintf(fd, "# %s.%s.total.num_types %d\n", xl->type, xl->name,
   27             xl->mem_acct->num_types);
   28 
   29     dprintf(fd,
   30             "# type, in-use-size, in-use-units, max-size, "
   31             "max-units, total-allocs\n");
   32 
   33     for (i = 0; i < xl->mem_acct->num_types; i++) {
   34         mem_rec = &xl->mem_acct->rec[i];
   35         if (mem_rec->num_allocs == 0)
   36             continue;
   37         dprintf(fd, "# %s, %" PRIu64 ", %u, %" PRIu64 ", %u, %" PRIu64 "\n",
   38                 mem_rec->typestr, mem_rec->size, mem_rec->num_allocs,
   39                 mem_rec->max_size, mem_rec->max_num_allocs,
   40                 mem_rec->total_allocs);
   41     }
   42 }
   43 
   44 static void
   45 dump_global_memory_accounting(int fd)
   46 {
   47 #if MEMORY_ACCOUNTING_STATS
   48     int i = 0;
   49     uint64_t count = 0;
   50 
   51     uint64_t tcalloc = GF_ATOMIC_GET(gf_memory_stat_counts.total_calloc);
   52     uint64_t tmalloc = GF_ATOMIC_GET(gf_memory_stat_counts.total_malloc);
   53     uint64_t tfree = GF_ATOMIC_GET(gf_memory_stat_counts.total_free);
   54 
   55     dprintf(fd, "memory.total.calloc %lu\n", tcalloc);
   56     dprintf(fd, "memory.total.malloc %lu\n", tmalloc);
   57     dprintf(fd, "memory.total.realloc %lu\n",
   58             GF_ATOMIC_GET(gf_memory_stat_counts.total_realloc));
   59     dprintf(fd, "memory.total.free %lu\n", tfree);
   60     dprintf(fd, "memory.total.in-use %lu\n", ((tcalloc + tmalloc) - tfree));
   61 
   62     for (i = 0; i < GF_BLK_MAX_VALUE; i++) {
   63         count = GF_ATOMIC_GET(gf_memory_stat_counts.blk_size[i]);
   64         dprintf(fd, "memory.total.blk_size.%s %lu\n",
   65                 gf_mem_stats_blk[i].blk_size_str, count);
   66     }
   67 
   68     dprintf(fd, "#----\n");
   69 #endif
   70 
   71     /* This is not a metric to be watched in admin guide,
   72        but keeping it here till we resolve all leak-issues
   73        would be great */
   74 }
   75 
   76 static void
   77 dump_latency_and_count(xlator_t *xl, int fd)
   78 {
   79     int32_t index = 0;
   80     uint64_t fop;
   81     uint64_t cbk;
   82     uint64_t count;
   83 
   84     if (xl->winds) {
   85         dprintf(fd, "%s.total.pending-winds.count %" PRIu64 "\n", xl->name,
   86                 xl->winds);
   87     }
   88 
   89     /* Need 'fuse' data, and don't need all the old graph info */
   90     if ((xl != xl->ctx->master) && (xl->ctx->active != xl->graph))
   91         return;
   92 
   93     count = GF_ATOMIC_GET(xl->stats.total.count);
   94     dprintf(fd, "%s.total.fop-count %" PRIu64 "\n", xl->name, count);
   95 
   96     count = GF_ATOMIC_GET(xl->stats.interval.count);
   97     dprintf(fd, "%s.interval.fop-count %" PRIu64 "\n", xl->name, count);
   98     GF_ATOMIC_INIT(xl->stats.interval.count, 0);
   99 
  100     for (index = 0; index < GF_FOP_MAXVALUE; index++) {
  101         fop = GF_ATOMIC_GET(xl->stats.total.metrics[index].fop);
  102         if (fop) {
  103             dprintf(fd, "%s.total.%s.count %" PRIu64 "\n", xl->name,
  104                     gf_fop_list[index], fop);
  105         }
  106         fop = GF_ATOMIC_GET(xl->stats.interval.metrics[index].fop);
  107         if (fop) {
  108             dprintf(fd, "%s.interval.%s.count %" PRIu64 "\n", xl->name,
  109                     gf_fop_list[index], fop);
  110         }
  111         cbk = GF_ATOMIC_GET(xl->stats.interval.metrics[index].cbk);
  112         if (cbk) {
  113             dprintf(fd, "%s.interval.%s.fail_count %" PRIu64 "\n", xl->name,
  114                     gf_fop_list[index], cbk);
  115         }
  116         if (xl->stats.interval.latencies[index].count != 0.0) {
  117             dprintf(fd, "%s.interval.%s.latency %lf\n", xl->name,
  118                     gf_fop_list[index],
  119                     (xl->stats.interval.latencies[index].total /
  120                      xl->stats.interval.latencies[index].count));
  121             dprintf(fd, "%s.interval.%s.max %lf\n", xl->name,
  122                     gf_fop_list[index],
  123                     xl->stats.interval.latencies[index].max);
  124             dprintf(fd, "%s.interval.%s.min %lf\n", xl->name,
  125                     gf_fop_list[index],
  126                     xl->stats.interval.latencies[index].min);
  127         }
  128         GF_ATOMIC_INIT(xl->stats.interval.metrics[index].cbk, 0);
  129         GF_ATOMIC_INIT(xl->stats.interval.metrics[index].fop, 0);
  130     }
  131     memset(xl->stats.interval.latencies, 0,
  132            sizeof(xl->stats.interval.latencies));
  133 }
  134 
  135 static inline void
  136 dump_call_stack_details(glusterfs_ctx_t *ctx, int fd)
  137 {
  138     dprintf(fd, "total.stack.count %" PRIu64 "\n",
  139             GF_ATOMIC_GET(ctx->pool->total_count));
  140     dprintf(fd, "total.stack.in-flight %" PRIu64 "\n", ctx->pool->cnt);
  141 }
  142 
  143 static inline void
  144 dump_dict_details(glusterfs_ctx_t *ctx, int fd)
  145 {
  146     uint64_t total_dicts = 0;
  147     uint64_t total_pairs = 0;
  148 
  149     total_dicts = GF_ATOMIC_GET(ctx->stats.total_dicts_used);
  150     total_pairs = GF_ATOMIC_GET(ctx->stats.total_pairs_used);
  151 
  152     dprintf(fd, "total.dict.max-pairs-per %" PRIu64 "\n",
  153             GF_ATOMIC_GET(ctx->stats.max_dict_pairs));
  154     dprintf(fd, "total.dict.pairs-used %" PRIu64 "\n", total_pairs);
  155     dprintf(fd, "total.dict.used %" PRIu64 "\n", total_dicts);
  156     dprintf(fd, "total.dict.average-pairs %" PRIu64 "\n",
  157             (total_pairs / total_dicts));
  158 }
  159 
  160 static void
  161 dump_inode_stats(glusterfs_ctx_t *ctx, int fd)
  162 {
  163 }
  164 
  165 static void
  166 dump_global_metrics(glusterfs_ctx_t *ctx, int fd)
  167 {
  168     struct timeval tv;
  169     time_t nowtime;
  170     struct tm *nowtm;
  171     char tmbuf[64] = {
  172         0,
  173     };
  174 
  175     gettimeofday(&tv, NULL);
  176     nowtime = tv.tv_sec;
  177     nowtm = localtime(&nowtime);
  178     strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
  179 
  180     /* Let every file have information on which process dumped info */
  181     dprintf(fd, "## %s\n", ctx->cmdlinestr);
  182     dprintf(fd, "### %s\n", tmbuf);
  183     dprintf(fd, "### BrickName: %s\n", ctx->cmd_args.brick_name);
  184     dprintf(fd, "### MountName: %s\n", ctx->cmd_args.mount_point);
  185     dprintf(fd, "### VolumeName: %s\n", ctx->cmd_args.volume_name);
  186 
  187     /* Dump memory accounting */
  188     dump_global_memory_accounting(fd);
  189     dprintf(fd, "# -----\n");
  190 
  191     dump_call_stack_details(ctx, fd);
  192     dump_dict_details(ctx, fd);
  193     dprintf(fd, "# -----\n");
  194 
  195     dump_inode_stats(ctx, fd);
  196     dprintf(fd, "# -----\n");
  197 }
  198 
  199 static void
  200 dump_xl_metrics(glusterfs_ctx_t *ctx, int fd)
  201 {
  202     xlator_t *xl;
  203 
  204     xl = ctx->active->top;
  205 
  206     while (xl) {
  207         dump_latency_and_count(xl, fd);
  208         dump_mem_acct_details(xl, fd);
  209         if (xl->dump_metrics)
  210             xl->dump_metrics(xl, fd);
  211         xl = xl->next;
  212     }
  213 
  214     if (ctx->master) {
  215         xl = ctx->master;
  216 
  217         dump_latency_and_count(xl, fd);
  218         dump_mem_acct_details(xl, fd);
  219         if (xl->dump_metrics)
  220             xl->dump_metrics(xl, fd);
  221     }
  222 
  223     return;
  224 }
  225 
  226 char *
  227 gf_monitor_metrics(glusterfs_ctx_t *ctx)
  228 {
  229     int ret = -1;
  230     int fd = 0;
  231     char *filepath = NULL, *dumppath = NULL;
  232 
  233     gf_msg_trace("monitoring", 0, "received monitoring request (sig:USR2)");
  234 
  235     dumppath = ctx->config.metrics_dumppath;
  236     if (dumppath == NULL) {
  237         dumppath = GLUSTER_METRICS_DIR;
  238     }
  239     ret = mkdir_p(dumppath, 0755, true);
  240     if (ret) {
  241         /* EEXIST is handled in mkdir_p() itself */
  242         gf_msg("monitoring", GF_LOG_ERROR, 0, LG_MSG_STRDUP_ERROR,
  243                "failed to create metrics dir %s (%s)", dumppath,
  244                strerror(errno));
  245         return NULL;
  246     }
  247 
  248     ret = gf_asprintf(&filepath, "%s/gmetrics.XXXXXX", dumppath);
  249     if (ret < 0) {
  250         return NULL;
  251     }
  252 
  253     /* coverity[secure_temp] mkstemp uses 0600 as the mode and is safe */
  254     fd = mkstemp(filepath);
  255     if (fd < 0) {
  256         gf_msg("monitoring", GF_LOG_ERROR, 0, LG_MSG_STRDUP_ERROR,
  257                "failed to open tmp file %s (%s)", filepath, strerror(errno));
  258         GF_FREE(filepath);
  259         return NULL;
  260     }
  261 
  262     dump_global_metrics(ctx, fd);
  263 
  264     dump_xl_metrics(ctx, fd);
  265 
  266     /* This below line is used just to capture any errors with dprintf() */
  267     ret = dprintf(fd, "\n# End of metrics\n");
  268     if (ret < 0) {
  269         gf_msg("monitoring", GF_LOG_WARNING, 0, LG_MSG_STRDUP_ERROR,
  270                "dprintf() failed: %s", strerror(errno));
  271     }
  272 
  273     ret = sys_fsync(fd);
  274     if (ret < 0) {
  275         gf_msg("monitoring", GF_LOG_WARNING, 0, LG_MSG_STRDUP_ERROR,
  276                "fsync() failed: %s", strerror(errno));
  277     }
  278     sys_close(fd);
  279 
  280     /* Figure this out, not happy with returning this string */
  281     return filepath;
  282 }