blob: 619508f1c24f58dbe20124aeee7f3b00eb18ce58 [file] [log] [blame]
//! @file
//!
//! Copyright (c) Memfault, Inc.
//! See LICENSE for details
//! @brief APIs for tracking reliability metrics
#include "memfault/metrics/reliability.h"
// non-module includes below
#include "memfault/components.h"
static sMemfaultMetricsReliabilityCtx s_memfault_metrics_reliability_ctx;
//! Load optional system state on boot.
void memfault_metrics_reliability_boot(sMemfaultMetricsReliabilityCtx *ctx) {
if (ctx != NULL) {
s_memfault_metrics_reliability_ctx = *ctx;
} else {
// Set the last heartbeat time to the current time since boot. This supports
// a system with a time-since-boot timer that counts through intentional
// resets (for example OTA).
s_memfault_metrics_reliability_ctx.last_heartbeat_ms =
memfault_platform_get_time_since_boot_ms();
}
}
sMemfaultMetricsReliabilityCtx *memfault_metrics_reliability_get_ctx(void) {
return &s_memfault_metrics_reliability_ctx;
}
// Accumulate operational hours.
void memfault_metrics_reliability_collect(void) {
// Accumulate ms since last heartbeat
const uint32_t time_since_boot_ms = memfault_platform_get_time_since_boot_ms();
const uint32_t this_interval_ms =
time_since_boot_ms - s_memfault_metrics_reliability_ctx.last_heartbeat_ms;
s_memfault_metrics_reliability_ctx.operational_ms += this_interval_ms;
// Count any accumulated hours
const uint32_t uptime_hours = s_memfault_metrics_reliability_ctx.operational_ms / 1000 / 3600;
// Deduct the counted hours from the accumulated ms
s_memfault_metrics_reliability_ctx.operational_ms -= uptime_hours * 3600 * 1000;
// Reset the accumulated ms for the next heartbeat
s_memfault_metrics_reliability_ctx.last_heartbeat_ms = time_since_boot_ms;
// Only report uptime if it's non-zero
if (!uptime_hours) {
return;
}
MEMFAULT_METRIC_ADD(operational_hours, (int32_t)uptime_hours);
bool unexpected_reboot = false;
if (!s_memfault_metrics_reliability_ctx.counted_unexpected_reboot) {
s_memfault_metrics_reliability_ctx.counted_unexpected_reboot = true;
(void)memfault_reboot_tracking_get_unexpected_reboot_occurred(&unexpected_reboot);
}
// Deduct an hour from the crashfree hours count if there was an unexpected
// reboot. This only applies to the first hour of uptime, which is where the
// crash is counted.
MEMFAULT_METRIC_ADD(operational_crashfree_hours,
(int32_t)(uptime_hours - (uint32_t)unexpected_reboot));
}