about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--filesystem.c74
2 files changed, 81 insertions, 7 deletions
diff --git a/README.md b/README.md
index 453b992..1114d4b 100644
--- a/README.md
+++ b/README.md
@@ -152,11 +152,21 @@ Metrics:
 
 Labels:
 
-* `device`: Device node mounted at the location.
+* `device`: Device node path mounted at the location.
 * `fstype`: Mounted filesystem type.
 * `mountpoint`: Location where the filesystem is mounted.
 
-TODO: inclusion/exclusion lists.
+By default, all mounts where the device path starts with an `/` are
+included. Command line arguments of the form
+`--filesystem-{in,ex}clude-{device,type,mount}=X,Y,Z` can be used to
+define comma-separated inclusion and exclusion lists for the device
+path, filesystem type and mountpoint labels, respectively. Each of the
+three categories is tested independently, and only if a mounted
+filesystem passes all three tests, it is included in the metrics. For
+each category, if an include list is specified, only the explicitly
+listed values are accepted -- this overrides even the `/` prefix test
+for devices. If an include list is not set, all values not on the
+exclusion list are accepted.
 
 The data is derived from scanning `/proc/mounts` and calling
 `statvfs(2)` on all lines that pass the inclusion checks.
diff --git a/filesystem.c b/filesystem.c
index d31518e..6ed4407 100644
--- a/filesystem.c
+++ b/filesystem.c
@@ -9,15 +9,59 @@
 // size of input buffer for paths and lines
 #define BUF_SIZE 256
 
+static void *filesystem_init(int argc, char *argv[]);
 static void filesystem_collect(scrape_req *req, void *ctx);
 
 const struct collector filesystem_collector = {
   .name = "filesystem",
   .collect = filesystem_collect,
+  .init = filesystem_init,
+  .has_args = true,
 };
 
-static void filesystem_collect(scrape_req *req, void *ctx) {
-  (void) ctx;
+struct filesystem_context {
+  struct slist *include_device;
+  struct slist *exclude_device;
+  struct slist *include_mount;
+  struct slist *exclude_mount;
+  struct slist *include_type;
+  struct slist *exclude_type;
+};
+
+static void *filesystem_init(int argc, char *argv[]) {
+  struct filesystem_context *ctx = must_malloc(sizeof *ctx);
+
+  ctx->include_device = 0;
+  ctx->exclude_device = 0;
+  ctx->include_mount = 0;
+  ctx->exclude_mount = 0;
+  ctx->include_type = 0;
+  ctx->exclude_type = 0;
+
+  for (int arg = 0; arg < argc; arg++) {
+    if (strncmp(argv[arg], "include-device=", 15) == 0) {
+      ctx->include_device = slist_split(&argv[arg][15], ",");
+    } else if (strncmp(argv[arg], "exclude-device=", 15) == 0) {
+      ctx->exclude_device = slist_split(&argv[arg][15], ",");
+    } else if (strncmp(argv[arg], "include-mount=", 14) == 0) {
+      ctx->include_mount = slist_split(&argv[arg][14], ",");
+    } else if (strncmp(argv[arg], "exclude-mount=", 14) == 0) {
+      ctx->exclude_mount = slist_split(&argv[arg][14], ",");
+    } else if (strncmp(argv[arg], "include-type=", 13) == 0) {
+      ctx->include_type = slist_split(&argv[arg][13], ",");
+    } else if (strncmp(argv[arg], "exclude-type=", 13) == 0) {
+      ctx->exclude_type = slist_split(&argv[arg][13], ",");
+    } else {
+      fprintf(stderr, "unknown argument for filesystem collector: %s", argv[arg]);
+      return 0;
+    }
+  }
+
+  return ctx;
+}
+
+static void filesystem_collect(scrape_req *req, void *ctx_ptr) {
+  struct filesystem_context *ctx = ctx_ptr;
 
   // buffers
 
@@ -56,9 +100,29 @@ static void filesystem_collect(scrape_req *req, void *ctx) {
     if (!*fstype)
       continue;
 
-    if (**dev != '/')
-      continue;
-    // TODO: device, mountpoint, filesystem exclude lists
+    if (ctx->include_device) {
+      if (!slist_contains(ctx->include_device, *dev))
+        continue;
+    } else {
+      if (**dev != '/')
+        continue;
+      if (ctx->exclude_device && slist_contains(ctx->exclude_device, *dev))
+        continue;
+    }
+    if (ctx->include_mount) {
+      if (!slist_contains(ctx->include_mount, *mount))
+        continue;
+    } else if (ctx->exclude_mount) {
+      if (slist_contains(ctx->exclude_mount, *mount))
+        continue;
+    }
+    if (ctx->include_type) {
+      if (!slist_contains(ctx->include_type, *fstype))
+        continue;
+    } else if (ctx->exclude_type) {
+      if (slist_contains(ctx->exclude_type, *fstype))
+        continue;
+    }
 
     // report metrics from statfs