@@ -137,6 +137,56 @@ static void prv_collect_memory_usage_metrics(void) {
137137}
138138#endif // defined(CONFIG_MEMFAULT_METRICS_MEMORY_USAGE)
139139
140+ #if defined(CONFIG_MEMFAULT_FS_BYTES_FREE_METRIC )
141+ void prv_collect_fs_bytes_free_metric (void ) {
142+ const char * mount_point = NULL ;
143+
144+ // User configured path takes priority
145+ #ifdef CONFIG_MEMFAULT_FS_BYTES_FREE_VFS_PATH
146+ char normalized_path [64 ];
147+ if (CONFIG_MEMFAULT_FS_BYTES_FREE_VFS_PATH [0 ] != '\0' ) {
148+ MEMFAULT_LOG_DEBUG ("Using user-configured mount point for FS bytes free metric" );
149+ snprintf (normalized_path , sizeof (normalized_path ), "/%s" ,
150+ CONFIG_MEMFAULT_FS_BYTES_FREE_VFS_PATH );
151+ mount_point = normalized_path ;
152+ }
153+ #endif
154+
155+ // Auto-detect from fstab only
156+ #if DT_NODE_EXISTS (DT_PATH (fstab ))
157+ MEMFAULT_LOG_DEBUG ("Auto-detecting mount point from fstab for FS bytes free metric" );
158+
159+ // Create a ternary chain to find the first mount point available
160+ //
161+ // The return statement here will expand to something like:
162+ // return (DT_NODE_HAS_PROP(child1, mount_point) ? DT_PROP(child1, mount_point) :)
163+ // (DT_NODE_HAS_PROP(child2, mount_point) ? DT_PROP(child2, mount_point) :)
164+ // (DT_NODE_HAS_PROP(child3, mount_point) ? DT_PROP(child3, mount_point) :)
165+ // NULL;
166+ #define FIND_FIRST_MOUNT (node_id ) \
167+ DT_NODE_HAS_PROP(node_id, mount_point) ? DT_PROP(node_id, mount_point):
168+
169+ mount_point = DT_FOREACH_CHILD_SEP (DT_PATH (fstab ), FIND_FIRST_MOUNT , ) NULL ;
170+ #endif
171+
172+ if (mount_point == NULL ) {
173+ MEMFAULT_LOG_WARN ("No mount point configured - skipping FS bytes free metric" );
174+ return ;
175+ }
176+
177+ MEMFAULT_LOG_DEBUG ("Collecting FS bytes free metric for mount point %s" , mount_point );
178+
179+ struct fs_statvfs fs_stats ;
180+ int retval = fs_statvfs (mount_point , & fs_stats );
181+ if (retval == 0 ) {
182+ // compute free bytes
183+ uint32_t bytes_free = fs_stats .f_frsize * fs_stats .f_bfree ;
184+ MEMFAULT_METRIC_SET_UNSIGNED (FileSystem_BytesFree , bytes_free );
185+ }
186+ }
187+
188+ #endif /* CONFIG_MEMFAULT_FS_BYTES_FREE_METRIC */
189+
140190// Written as a function vs. in-line b/c we might want to extern this at some point?
141191// See ports/zephyr/config/memfault_metrics_heartbeat_zephyr_port_config.def for
142192// where the metrics key names come from.
@@ -181,20 +231,12 @@ void memfault_metrics_heartbeat_collect_sdk_data(void) {
181231 // for percentage conversion
182232 uint32_t usage_pct = (uint32_t )(non_idle_tasks_cycles_delta * 10000 / all_tasks_cycles_delta );
183233 MEMFAULT_METRIC_SET_UNSIGNED (cpu_usage_pct , usage_pct );
184- MEMFAULT_LOG_DEBUG ("CPU usage: %u.%02u%%\n " , usage_pct / 100 , usage_pct % 100 );
234+ MEMFAULT_LOG_DEBUG ("CPU usage: %u.%02u%%" , usage_pct / 100 , usage_pct % 100 );
185235 }
186236 #endif // MEMFAULT_ZEPHYR_VERSION_GT_STRICT(3, 0)
187237
188- #if CONFIG_MEMFAULT_FS_BYTES_FREE_METRIC
189- {
190- struct fs_statvfs fs_stats ;
191- int retval = fs_statvfs ("/" CONFIG_MEMFAULT_FS_BYTES_FREE_VFS_PATH , & fs_stats );
192- if (retval == 0 ) {
193- // compute free bytes
194- uint32_t bytes_free = fs_stats .f_frsize * fs_stats .f_bfree ;
195- MEMFAULT_METRIC_SET_UNSIGNED (FileSystem_BytesFree , bytes_free );
196- }
197- }
238+ #if defined(CONFIG_MEMFAULT_FS_BYTES_FREE_METRIC )
239+ prv_collect_fs_bytes_free_metric ();
198240 #endif /* CONFIG_MEMFAULT_FS_BYTES_FREE_METRIC */
199241
200242#endif /* CONFIG_MEMFAULT_METRICS_DEFAULT_SET_ENABLE */
0 commit comments