about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHeikki Kallasjoki <fis@zem.fi>2018-11-17 02:52:19 +0000
committerHeikki Kallasjoki <fis@zem.fi>2018-11-30 01:28:01 +0000
commit9784d8743daf4eb4d298c15ae6d3c8fa19faf486 (patch)
tree3403741fc244bef20d991f89f6676f1eab1438b3
parent5ed9c0224214147e9e8321e491d7b4556b818e49 (diff)
downloadnano-exporter-9784d8743daf4eb4d298c15ae6d3c8fa19faf486.tar.gz
nano-exporter-9784d8743daf4eb4d298c15ae6d3c8fa19faf486.tar.xz
nano-exporter-9784d8743daf4eb4d298c15ae6d3c8fa19faf486.zip
Add the meminfo collector.
-rw-r--r--README.md13
-rw-r--r--main.c2
-rw-r--r--meminfo.c76
-rw-r--r--meminfo.h8
4 files changed, 99 insertions, 0 deletions
diff --git a/README.md b/README.md
index e9e6abb..7ea87fa 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,7 @@ including generated metrics, labels and configuration options.
 | ---- | ----------- |
 | [`cpu`](#cpu) | CPU usage from `/proc/stat` and CPU frequency scaling data from sysfs. |
 | [`hwmon`](#hwmon) | Temperature, fan and voltage sensors from `/sys/class/hwmon`. |
+| [`meminfo`](#meminfo) | Memory usage statistics from `/proc/meminfo`. |
 | [`network`](#network) | Network device transmit/receive statistics from `/proc/net/dev`. |
 | [`textfile`](#textfile) | Custom metrics from `.prom` text files dropped in a directory. |
 | [`uname`](#uname) | Node information returned by the `uname` system call. |
@@ -106,6 +107,18 @@ chip.
 The values are by default directly as reported in sysfs: there's no
 built-in scaling. TODO: scaling options.
 
+### `meminfo`
+
+The `meminfo` collector exposes all the rows from `/proc/meminfo`
+under the metric name `node_memory_X`. The part *X* corresponds to the
+label in `/proc/meminfo`, with the exception that non-alphanumeric
+characters are replaced with `_`, and any remaining trailing `_`s are
+removed.
+
+If the line in `/proc/meminfo` has a `kB` suffix, the suffix `_bytes`
+is also appended to the metric name, and the value multiplied by 1024
+to convert it to bytes.
+
 ### `network`
 
 Metrics and labels:
diff --git a/main.c b/main.c
index a67e5d2..84647d0 100644
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
 
 #include "cpu.h"
 #include "hwmon.h"
+#include "meminfo.h"
 #include "network.h"
 #include "scrape.h"
 #include "textfile.h"
@@ -16,6 +17,7 @@
 static const struct collector *collectors[] = {
   &cpu_collector,
   &hwmon_collector,
+  &meminfo_collector,
   &network_collector,
   &textfile_collector,
   &uname_collector,
diff --git a/meminfo.c b/meminfo.c
new file mode 100644
index 0000000..982400a
--- /dev/null
+++ b/meminfo.c
@@ -0,0 +1,76 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "meminfo.h"
+#include "util.h"
+
+// size of input buffer for paths and lines
+#define BUF_SIZE 256
+
+// prefix to add to /proc/meminfo lines; must fit in BUF_SIZE
+#define METRIC_PREFIX "node_memory_"
+#define METRIC_PREFIX_LEN (sizeof METRIC_PREFIX - 1)
+
+// suffix to add for " kB" metrics
+#define BYTES_SUFFIX "_bytes"
+#define BYTES_SUFFIX_LEN (sizeof BYTES_SUFFIX - 1)
+
+static void meminfo_collect(scrape_req *req, void *ctx);
+
+const struct collector meminfo_collector = {
+  .name = "meminfo",
+  .collect = meminfo_collect,
+};
+
+static void meminfo_collect(scrape_req *req, void *ctx) {
+  // buffers
+
+  char buf[BUF_SIZE] = METRIC_PREFIX;
+
+  FILE *f;
+
+  // convert /proc/meminfo to metrics format
+
+  f = fopen("/proc/meminfo", "r");
+  if (!f)
+    return;
+
+  while (fgets_line(buf + METRIC_PREFIX_LEN, sizeof buf - METRIC_PREFIX_LEN, f)) {
+    char *p = buf + METRIC_PREFIX_LEN;
+    while (*p != '\0' && *p != ':') {
+      if (!isalnum((unsigned char)*p))
+        *p = '_';
+      p++;
+    }
+    if (*p != ':')
+      continue;
+    char *metric_end = p;
+
+    while (metric_end > buf + METRIC_PREFIX_LEN && metric_end[-1] == '_')
+      --metric_end;
+    *metric_end = '\0';
+
+    do p++; while (*p == ' ');
+
+    double value = strtod(p, &p);
+    if (*p != '\0' && *p != ' ')
+      continue;
+
+    if (*p == ' ') {
+      do p++; while (*p == ' ');
+      if (p[0] == 'k' && p[1] == 'B') {
+        if ((metric_end - buf) + BYTES_SUFFIX_LEN >= sizeof buf)
+          continue;
+        strcpy(metric_end, BYTES_SUFFIX);
+        value *= 1024.0;
+      }
+    }
+
+    scrape_write(req, buf, 0, value);
+  }
+
+  fclose(f);
+}
diff --git a/meminfo.h b/meminfo.h
new file mode 100644
index 0000000..76c9339
--- /dev/null
+++ b/meminfo.h
@@ -0,0 +1,8 @@
+#ifndef PNANOE_MEMINFO_H_
+#define PNANOE_MEMINFO_H_ 1
+
+#include "collector.h"
+
+extern const struct collector meminfo_collector;
+
+#endif // PNANOE_MEMINFO_H_