diff --git a/src/builder/CMakeLists.txt b/src/builder/CMakeLists.txt
index 1d24227..9160968 100644
--- a/src/builder/CMakeLists.txt
+++ b/src/builder/CMakeLists.txt
@@ -11,6 +11,7 @@ set(SRCS
b-logproxy.c
b-refproxy.c
b-load.c
+ b-metrics.c
../common/c-utils.c
)
diff --git a/src/builder/b-comms.c b/src/builder/b-comms.c
index 80116b6..8f955e4 100644
--- a/src/builder/b-comms.c
+++ b/src/builder/b-comms.c
@@ -482,6 +482,8 @@ saib_sul_load_report_cb(struct lws_sorted_usec_list *sul)
*/
lws_strncpy(lr->builder_name, builder.host, sizeof(lr->builder_name));
lr->core_count = saib_get_cpu_count();
+ lr->free_ram_kib = saib_get_free_ram_kib();
+ lr->free_disk_kib = saib_get_free_disk_kib(builder.home);
int system_load = saib_get_system_cpu(&builder);
diff --git a/src/builder/b-metrics.c b/src/builder/b-metrics.c
new file mode 100644
index 0000000..b577f73
--- /dev/null
+++ b/src/builder/b-metrics.c
@@ -0,0 +1,100 @@
+/*
+ * sai-builder-metrics
+ *
+ * Copyright (C) 2019 - 2021 Andy Green <andy@warmcat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation:
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <libwebsockets.h>
+#include "b-private.h"
+
+#if defined(__linux__)
+#include <sys/statvfs.h>
+#elif defined(__APPLE__)
+#include <sys/sysctl.h>
+#include <mach/mach.h>
+#include <mach/vm_statistics.h>
+#endif
+
+unsigned int
+saib_get_free_ram_kib(void)
+{
+#if defined(__linux__)
+ char buf[256];
+ FILE *f;
+ unsigned int free_kib = 0;
+
+ f = fopen("/proc/meminfo", "r");
+ if (!f)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), f)) {
+ if (sscanf(buf, "MemAvailable: %u kB", &free_kib) == 1)
+ break;
+ }
+
+ fclose(f);
+ return free_kib;
+#elif defined(__APPLE__)
+ int mib[2];
+ size_t len;
+ uint64_t total_mem;
+ vm_size_t page_size;
+ mach_msg_type_number_t count;
+ vm_statistics64_data_t vm_stats;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ len = sizeof(total_mem);
+ sysctl(mib, 2, &total_mem, &len, NULL, 0);
+
+ count = HOST_VM_INFO64_COUNT;
+ if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stats, &count) != KERN_SUCCESS)
+ return 0;
+
+ return (unsigned int)((uint64_t)vm_stats.free_count * vm_stats.pagesize / 1024);
+#elif defined(_WIN32)
+ MEMORYSTATUSEX statex;
+ statex.dwLength = sizeof(statex);
+ GlobalMemoryStatusEx(&statex);
+ return (unsigned int)(statex.ullAvailPhys / 1024);
+#else
+ return 0;
+#endif
+}
+
+unsigned int
+saib_get_free_disk_kib(const char *path)
+{
+#if defined(__linux__) || defined(__APPLE__)
+ struct statvfs s;
+
+ if (statvfs(path, &s))
+ return 0;
+
+ return (unsigned int)((uint64_t)s.f_bavail * s.f_frsize / 1024);
+#elif defined(_WIN32)
+ ULARGE_INTEGER free_bytes;
+
+ if (!GetDiskFreeSpaceExA(path, &free_bytes, NULL, NULL))
+ return 0;
+
+ return (unsigned int)(free_bytes.QuadPart / 1024);
+#else
+ return 0;
+#endif
+}
diff --git a/src/builder/b-private.h b/src/builder/b-private.h
index 4f1c75b..7146d14 100644
--- a/src/builder/b-private.h
+++ b/src/builder/b-private.h
@@ -229,3 +229,8 @@ saib_get_system_cpu(struct sai_builder *b);
int saib_get_cpu_count(void);
+unsigned int
+saib_get_free_ram_kib(void);
+
+unsigned int
+saib_get_free_disk_kib(const char *path);
diff --git a/src/common/include/private.h b/src/common/include/private.h
index f821db3..6b017a1 100644
--- a/src/common/include/private.h
+++ b/src/common/include/private.h
@@ -85,6 +85,8 @@ typedef struct sai_load_report {
char builder_name[64];
int core_count;
lws_dll2_owner_t platforms; /* List of sai_platform_load_t */
+ unsigned int free_ram_kib;
+ unsigned int free_disk_kib;
} sai_load_report_t;
/*
diff --git a/src/common/struct-metadata.c b/src/common/struct-metadata.c
index 73dc8ea..7d62719 100644
--- a/src/common/struct-metadata.c
+++ b/src/common/struct-metadata.c
@@ -36,6 +36,8 @@ const lws_struct_map_t lsm_platform_load[] = {
const lws_struct_map_t lsm_load_report_members[] = {
LSM_CARRAY (sai_load_report_t, builder_name, "builder_name"),
LSM_SIGNED (sai_load_report_t, core_count, "core_count"),
+ LSM_UNSIGNED (sai_load_report_t, free_ram_kib, "free_ram_kib"),
+ LSM_UNSIGNED (sai_load_report_t, free_disk_kib, "free_disk_kib"),
LSM_LIST (sai_load_report_t, platforms, sai_platform_load_t, list,
NULL, lsm_platform_load, "platforms"),
};