diff --git a/Makefile b/Makefile index 252f8b9..5540089 100644 --- a/Makefile +++ b/Makefile @@ -2,16 +2,19 @@ GIT_VERSION := $(shell git --no-pager describe --tags --always --long | sed "s/v all: build/node_exporter_aix -build/node_exporter_aix: build/server.o build/collectors.o build/main.o - g++ -Wall -Werror -fmax-errors=5 -fconcepts -std=c++17 -pthread -lperfstat -DUSE_STANDALONE_ASIO -DASIO_STANDALONE -DASIO_HAS_PTHREADS -static-libgcc -Wl,-bstatic -lstdc++ -lgcc -Wl,-bdynamic -o build/node_exporter_aix build/server.o build/collectors.o build/main.o +build/node_exporter_aix: build/server.o build/collectors.o build/main.o build/mounts.o + g++ -Wall -Werror -fmax-errors=5 -fconcepts -std=c++17 -pthread -lperfstat -DUSE_STANDALONE_ASIO -DASIO_STANDALONE -DASIO_HAS_PTHREADS -static-libgcc -Wl,-bstatic -lstdc++ -lgcc -Wl,-bdynamic -o build/node_exporter_aix build/server.o build/collectors.o build/main.o build/mounts.o -build/server.o: server.cpp +build/server.o: server.cpp node_exporter_aix.hpp g++ -Wall -Werror -fmax-errors=5 -fconcepts -std=c++17 -pthread -lperfstat -I Simple-Web-Server -I asio/asio/include -DUSE_STANDALONE_ASIO -DASIO_STANDALONE -DASIO_HAS_PTHREADS -c -o build/server.o server.cpp -build/main.o: main.cpp +build/main.o: main.cpp node_exporter_aix.hpp g++ -Wall -Werror -fmax-errors=5 -fconcepts -std=c++17 -pthread -lperfstat -DUSE_STANDALONE_ASIO -DASIO_STANDALONE -DASIO_HAS_PTHREADS -D PROG_VERSION="\"$(GIT_VERSION)\"" -c -o build/main.o main.cpp -build/collectors.o: collectors.cpp generated/diskpaths.cpp generated/diskadapters.cpp generated/memory_pages.cpp generated/memory.cpp generated/cpus.cpp generated/disks.cpp generated/netinterfaces.cpp generated/netadapters.cpp generated/netbuffers.cpp generated/partition.cpp +build/mounts.o: mounts.cpp node_exporter_aix.hpp + g++ -Wall -Werror -fmax-errors=5 -fconcepts -std=c++17 -pthread -lperfstat -DUSE_STANDALONE_ASIO -DASIO_STANDALONE -DASIO_HAS_PTHREADS -D PROG_VERSION="\"$(GIT_VERSION)\"" -c -o build/mounts.o mounts.cpp + +build/collectors.o: collectors.cpp generated/diskpaths.cpp generated/diskadapters.cpp generated/memory_pages.cpp generated/memory.cpp generated/cpus.cpp generated/disks.cpp generated/netinterfaces.cpp generated/netadapters.cpp generated/netbuffers.cpp generated/partition.cpp node_exporter_aix.hpp g++ -Wall -Werror -fmax-errors=5 -fconcepts -std=c++17 -pthread -lperfstat -DUSE_STANDALONE_ASIO -DASIO_STANDALONE -DASIO_HAS_PTHREADS -c -o build/collectors.o collectors.cpp generated/%s.cpp: data_sources/%.multiple scripts/generate_multiple.ksh templates/generate_multiple.template diff --git a/collectors.cpp b/collectors.cpp index c12303f..b7c549d 100644 --- a/collectors.cpp +++ b/collectors.cpp @@ -6,6 +6,8 @@ #include #include +#include "node_exporter_aix.hpp" + std::string generate_static_labels() { std::ostringstream labels; static std::string output_str; @@ -96,6 +98,46 @@ void gather_cpu_compat(std::ostringstream& response, const std::string& static_l output_cpu_stat(response, static_labels, "node_intr", "counter", "Total number of interrupts serviced.", cpu, [](perfstat_cpu_total_t& cpu) { return (double)cpu.decrintrs + (double)cpu.mpcrintrs + (double)cpu.mpcsintrs + (double)cpu.devintrs + (double)cpu.softintrs; }); } +void gather_filesystems(std::ostringstream& response, const std::string& static_labels) { + std::vector filesystems = stat_filesystems(list_mounts()); + + response << "# HELP node_filesystem_size_bytes Filesystem size in bytes." << std::endl; + response << "# TYPE node_filesystem_size_bytes gauge" << std::endl; + for(auto it = filesystems.begin(); it < filesystems.end(); it++) { + response << "node_filesystem_size_bytes{device=\"" << (*it).device << "\",fstype=\"jfs2\",mountpoint=\"" << (*it).mountpoint << "\"," << static_labels << "} " << (*it).size_bytes << std::endl; + } + + response << "# HELP node_filesystem_free_bytes Filesystem free space in bytes." << std::endl; + response << "# TYPE node_filesystem_free_bytes gauge" << std::endl; + for(auto it = filesystems.begin(); it < filesystems.end(); it++) { + response << "node_filesystem_free_bytes{device=\"" << (*it).device << "\",fstype=\"jfs2\",mountpoint=\"" << (*it).mountpoint << "\"," << static_labels << "} " << (*it).free_bytes << std::endl; + } + + response << "# HELP node_filesystem_avail_bytes Filesystem space available to non-root users in bytes." << std::endl; + response << "# TYPE node_filesystem_avail_bytes gauge" << std::endl; + for(auto it = filesystems.begin(); it < filesystems.end(); it++) { + response << "node_filesystem_avail_bytes{device=\"" << (*it).device << "\",fstype=\"jfs2\",mountpoint=\"" << (*it).mountpoint << "\"," << static_labels << "} " << (*it).avail_bytes << std::endl; + } + + response << "# HELP node_filesystem_files Filesystem total file nodes." << std::endl; + response << "# TYPE node_filesystem_files gauge" << std::endl; + for(auto it = filesystems.begin(); it < filesystems.end(); it++) { + response << "node_filesystem_files{device=\"" << (*it).device << "\",fstype=\"jfs2\",mountpoint=\"" << (*it).mountpoint << "\"," << static_labels << "} " << (*it).files << std::endl; + } + + response << "# HELP node_filesystem_files_free Filesystem total free file nodes." << std::endl; + response << "# TYPE node_filesystem_files_free gauge" << std::endl; + for(auto it = filesystems.begin(); it < filesystems.end(); it++) { + response << "node_filesystem_files_free{device=\"" << (*it).device << "\",fstype=\"jfs2\",mountpoint=\"" << (*it).mountpoint << "\"," << static_labels << "} " << (*it).files_free << std::endl; + } + + response << "# HELP node_filesystem_files_avail Filesystem available file nodes to non-root users." << std::endl; + response << "# TYPE node_filesystem_files_avail gauge" << std::endl; + for(auto it = filesystems.begin(); it < filesystems.end(); it++) { + response << "node_filesystem_files_avail{device=\"" << (*it).device << "\",fstype=\"jfs2\",mountpoint=\"" << (*it).mountpoint << "\"," << static_labels << "} " << (*it).files_avail << std::endl; + } +} + #include "generated/diskadapters.cpp" #include "generated/diskpaths.cpp" #include "generated/memory_pages.cpp" diff --git a/main.cpp b/main.cpp index 4da1247..70dceaf 100644 --- a/main.cpp +++ b/main.cpp @@ -28,6 +28,7 @@ int usage(int c) { std::cout << " -a net adapter statistics" << std::endl; std::cout << " -b net buffer statistics" << std::endl; std::cout << " -P partition statistics" << std::endl; + std::cout << " -f filesystem statistics" << std::endl; return 1; } @@ -39,7 +40,7 @@ int main(int argc, char **argv) { int flags = 0, port = 9100; - while((c = getopt(argc, argv, "p:CcAPMmdiabph?")) != EOF) { + while((c = getopt(argc, argv, "p:CcAPMmdiabpfh?")) != EOF) { switch(c) { case 'p': port = std::stoi(optarg); break; case 'C': flags |= PART_COMPAT; break; @@ -53,6 +54,7 @@ int main(int argc, char **argv) { case 'a': flags |= PART_NETADAPTER; break; case 'b': flags |= PART_NETBUFFER; break; case 'P': flags |= PART_PARTITION; break; + case 'f': flags |= PART_FILESYSTEMS; break; case 'h': usage(c); return 0; break; case '?': usage(c); return 0; break; default: diff --git a/node_exporter_aix.hpp b/node_exporter_aix.hpp index 7cbac22..7ad20b1 100644 --- a/node_exporter_aix.hpp +++ b/node_exporter_aix.hpp @@ -1,3 +1,6 @@ +#include +#include + #define PART_COMPAT (1<<0) #define PART_CPU (1<<1) #define PART_DISKADAPTER (1<<2) @@ -8,7 +11,8 @@ #define PART_NETINTERFACE (1<<7) #define PART_NETADAPTER (1<<8) #define PART_NETBUFFER (1<<9) -#define PART_PARTITION (1<<20) +#define PART_PARTITION (1<<10) +#define PART_FILESYSTEMS (1<<11) extern int start_server(int port, int flags); @@ -27,3 +31,23 @@ extern void gather_netinterfaces(std::ostringstream& response, const std::string extern void gather_netadapters(std::ostringstream& response, const std::string& static_labels); extern void gather_netbuffers(std::ostringstream& response, const std::string& static_labels); extern void gather_partition(std::ostringstream& response, const std::string& static_labels); +extern void gather_filesystems(std::ostringstream& response, const std::string& static_labels); + +struct mountpoint { + std::string mountpoint; + std::string device; +}; + +struct filesystem { + std::string mountpoint; + std::string device; + u_int64 avail_bytes; // f_bavail + u_int64 size_bytes; // f_bfrsize + u_int64 free_bytes; // f_bfree + u_int64 files; // f_files + u_int64 files_free; // f_ffree + u_int64 files_avail; // f_favail +}; + +extern std::vector list_mounts(); +extern std::vector stat_filesystems(std::vector mounts); diff --git a/server.cpp b/server.cpp index d2afb8e..8067758 100644 --- a/server.cpp +++ b/server.cpp @@ -37,6 +37,7 @@ int start_server(int port, int flags) { if(flags & PART_NETADAPTER) gather_netadapters(output, static_labels); if(flags & PART_NETBUFFER) gather_netbuffers(output, static_labels); if(flags & PART_PARTITION) gather_partition(output, static_labels); + if(flags & PART_FILESYSTEMS) gather_filesystems(output, static_labels); auto outstr = output.str(); *response << "HTTP/1.1 200 OK\r\nContent-Length: " << outstr.length() << "\r\n\r\n"