From: Michael Tremer Date: Sun, 5 Oct 2025 11:55:23 +0000 (+0000) Subject: Add source for memory usage X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a344d83472dbe3781024a0bb0752c54ed33bccb1;p=collecty.git Add source for memory usage Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 1cd98a0..58bd9cf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -134,6 +134,8 @@ dist_collectyd_SOURCES = \ src/daemon/sources/df.h \ src/daemon/sources/loadavg.c \ src/daemon/sources/loadavg.h \ + src/daemon/sources/memory.c \ + src/daemon/sources/memory.h \ src/daemon/sources/pressure-cpu.c \ src/daemon/sources/pressure-cpu.h \ src/daemon/sources/pressure-io.c \ diff --git a/src/daemon/proc.c b/src/daemon/proc.c index e22f6ef..9fad49a 100644 --- a/src/daemon/proc.c +++ b/src/daemon/proc.c @@ -27,6 +27,77 @@ #include "proc.h" +int collecty_proc_read_meminfo(collecty_ctx* ctx, collecty_proc_meminfo* meminfo) { + unsigned long v; + FILE* f = NULL; + char k[64]; + int r; + + // Open /proc/meminfo + f = fopen("/proc/meminfo", "r"); + if (!f) + return -errno; + + // Read line by line + for (;;) { + r = fscanf(f, "%63s %lu kB\n", k, &v); + if (r < 0) + break; + + // Skip any lines that could not be parsed + if (r < 2) + continue; + + // Convert the value from kB into Bytes + v *= 1024; + + // Store the values + if (strcmp("MemTotal:", k) == 0) + meminfo->mem_total = v; + else if (strcmp("MemFree:", k) == 0) + meminfo->mem_free = v; + else if (strcmp("MemAvailable:", k) == 0) + meminfo->mem_available = v; + else if (strcmp("Cached:", k) == 0) + meminfo->cached = v; + else if (strcmp("Buffers:", k) == 0) + meminfo->buffers = v; + else if (strcmp("Active:", k) == 0) + meminfo->active = v; + else if (strcmp("Inactive:", k) == 0) + meminfo->inactive = v; + else if (strcmp("Active(anon):", k) == 0) + meminfo->active_anon = v; + else if (strcmp("Inactive(anon):", k) == 0) + meminfo->inactive_anon = v; + else if (strcmp("Active(file):", k) == 0) + meminfo->active_file = v; + else if (strcmp("Inactive(file):", k) == 0) + meminfo->inactive_file = v; + else if (strcmp("SwapTotal:", k) == 0) + meminfo->swap_total = v; + else if (strcmp("SwapFree:", k) == 0) + meminfo->swap_free = v; + else if (strcmp("Shmem:", k) == 0) + meminfo->shmem = v; + else if (strcmp("Slab:", k) == 0) + meminfo->slab = v; + else if (strcmp("SReclaimable:", k) == 0) + meminfo->sreclaimable = v; + else if (strcmp("SUnreclaim:", k) == 0) + meminfo->sunreclaim = v; + } + + // Success + r = 0; + + // Cleanup + if (f) + fclose(f); + + return r; +} + static int collecty_proc_read_stat_line(collecty_ctx* ctx, const char* tag, char* line, unsigned long* fields, size_t max_fields) { char* p = NULL; diff --git a/src/daemon/proc.h b/src/daemon/proc.h index e3f6aae..2dfb62c 100644 --- a/src/daemon/proc.h +++ b/src/daemon/proc.h @@ -22,9 +22,35 @@ #define COLLECTY_PROC_H #include +#include #include "ctx.h" +typedef struct collecty_proc_meminfo { + // Memory + uint64_t mem_total; + uint64_t mem_free; + uint64_t mem_available; + uint64_t cached; + uint64_t buffers; + uint64_t active; + uint64_t inactive; + uint64_t active_anon; + uint64_t inactive_anon; + uint64_t active_file; + uint64_t inactive_file; + uint64_t shmem; + uint64_t slab; + uint64_t sreclaimable; + uint64_t sunreclaim; + + // Swap + uint64_t swap_total; + uint64_t swap_free; +} collecty_proc_meminfo; + +int collecty_proc_read_meminfo(collecty_ctx* ctx, collecty_proc_meminfo* meminfo); + int collecty_proc_read_stat(collecty_ctx* ctx, const char* tag, unsigned long* fields, size_t max_fields); diff --git a/src/daemon/sources.c b/src/daemon/sources.c index 309bc68..5381b61 100644 --- a/src/daemon/sources.c +++ b/src/daemon/sources.c @@ -32,6 +32,7 @@ #include "sources/contextswitches.h" #include "sources/df.h" #include "sources/loadavg.h" +#include "sources/memory.h" #include "sources/pressure-cpu.h" #include "sources/pressure-io.h" #include "sources/pressure-memory.h" @@ -46,6 +47,7 @@ static const collecty_source_impl* source_impls[] = { &contextswitches_source, &df_source, &loadavg_source, + &memory_source, &pressure_cpu_source, &pressure_io_source, &pressure_memory_source, diff --git a/src/daemon/sources/memory.c b/src/daemon/sources/memory.c new file mode 100644 index 0000000..dd06f1b --- /dev/null +++ b/src/daemon/sources/memory.c @@ -0,0 +1,75 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include "../ctx.h" +#include "../proc.h" +#include "../source.h" +#include "memory.h" + +static int memory_collect(collecty_ctx* ctx, collecty_source* source) { + collecty_proc_meminfo meminfo = {}; + int r; + + // Read all values from /proc/meminfo + r = collecty_proc_read_meminfo(ctx, &meminfo); + if (r < 0) + return r; + + // Submit the values + return collecty_source_submit(source, NULL, + "%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu:%lu", + meminfo.mem_total, meminfo.mem_free, meminfo.mem_available, + meminfo.cached, meminfo.buffers, meminfo.active, meminfo.inactive, + meminfo.active_anon, meminfo.inactive_anon, meminfo.active_file, + meminfo.inactive_file, meminfo.shmem, meminfo.slab, meminfo.sreclaimable, + meminfo.sunreclaim, meminfo.swap_total, meminfo.swap_free); +} + +const collecty_source_impl memory_source = { + .name = "memory", + + // RRD Data Sources + .rrd_dss = { + // Memory + { "mem_total", "GAUGE", 0, -1, }, + { "mem_free", "GAUGE", 0, -1, }, + { "mem_available", "GAUGE", 0, -1, }, + { "cached", "GAUGE", 0, -1, }, + { "buffers", "GAUGE", 0, -1, }, + { "active", "GAUGE", 0, -1, }, + { "inactive", "GAUGE", 0, -1, }, + { "active_anon", "GAUGE", 0, -1, }, + { "inactive_anon", "GAUGE", 0, -1, }, + { "active_file", "GAUGE", 0, -1, }, + { "inactive_file", "GAUGE", 0, -1, }, + { "shmem", "GAUGE", 0, -1, }, + { "slab", "GAUGE", 0, -1, }, + { "sreclaimable", "GAUGE", 0, -1, }, + { "sunreclaimable", "GAUGE", 0, -1, }, + + // Swap + { "swap_total", "GAUGE", 0, -1, }, + { "swap_free", "GAUGE", 0, -1, }, + { NULL }, + }, + + // Methods + .collect = memory_collect, +}; diff --git a/src/daemon/sources/memory.h b/src/daemon/sources/memory.h new file mode 100644 index 0000000..f95aa5f --- /dev/null +++ b/src/daemon/sources/memory.h @@ -0,0 +1,28 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#ifndef COLLECTY_SOURCE_MEMORY_H +#define COLLECTY_SOURCE_MEMORY_H + +#include "../source.h" + +extern const collecty_source_impl memory_source; + +#endif /* COLLECTY_SOURCE_MEMORY_H */