2121#include "memfault/core/math.h"
2222#include "memfault/core/platform/debug_log.h"
2323#include "memfault/core/platform/overrides.h"
24+ #include "memfault/core/platform/system_time.h"
2425#include "memfault/core/sdk_assert.h"
2526#include "memfault/util/base64.h"
2627#include "memfault/util/circular_buffer.h"
@@ -97,15 +98,17 @@ bool memfault_log_get_regions(sMemfaultLogRegions *regions) {
9798 return true;
9899}
99100
100- static uint8_t prv_build_header (eMemfaultPlatformLogLevel level , eMemfaultLogRecordType type ) {
101+ static uint8_t prv_build_header (eMemfaultPlatformLogLevel level , eMemfaultLogRecordType type ,
102+ bool timestamped ) {
101103 MEMFAULT_STATIC_ASSERT (kMemfaultPlatformLogLevel_NumLevels <= 8 ,
102104 "Number of log levels exceed max number that log module can track" );
103105 MEMFAULT_STATIC_ASSERT (kMemfaultLogRecordType_NumTypes <= 2 ,
104106 "Number of log types exceed max number that log module can track" );
105107
106108 const uint8_t level_field = (level << MEMFAULT_LOG_HDR_LEVEL_POS ) & MEMFAULT_LOG_HDR_LEVEL_MASK ;
107109 const uint8_t type_field = (type << MEMFAULT_LOG_HDR_TYPE_POS ) & MEMFAULT_LOG_HDR_TYPE_MASK ;
108- return level_field | type_field ;
110+ const uint8_t timestamped_field = timestamped ? MEMFAULT_LOG_HDR_TIMESTAMPED_MASK : 0 ;
111+ return level_field | type_field | timestamped_field ;
109112}
110113
111114void memfault_log_set_min_save_level (eMemfaultPlatformLogLevel min_log_level ) {
@@ -225,10 +228,21 @@ static bool prv_read_log_iter_callback(sMfltLogIterator *iter) {
225228 return false;
226229 }
227230
228- ctx -> log -> msg [iter -> entry .len ] = '\0' ;
229231 ctx -> log -> level = memfault_log_get_level_from_hdr (iter -> entry .hdr );
230232 ctx -> log -> type = memfault_log_get_type_from_hdr (iter -> entry .hdr );
231233 ctx -> log -> msg_len = iter -> entry .len ;
234+ #if MEMFAULT_LOG_TIMESTAMPS_ENABLE
235+ const size_t timestamp_len = sizeof (ctx -> log -> timestamp );
236+ if (memfault_log_hdr_is_timestamped (iter -> entry .hdr ) && (iter -> entry .len >= timestamp_len )) {
237+ memcpy (& ctx -> log -> timestamp , ctx -> log -> msg , timestamp_len );
238+ // shift the message over to remove the timestamp
239+ memmove (ctx -> log -> msg , & ctx -> log -> msg [timestamp_len ], ctx -> log -> msg_len - timestamp_len );
240+ ctx -> log -> msg_len -= timestamp_len ;
241+ } else {
242+ ctx -> log -> timestamp = 0 ;
243+ }
244+ #endif
245+ ctx -> log -> msg [ctx -> log -> msg_len ] = '\0' ;
232246 ctx -> has_log = true;
233247 return false;
234248}
@@ -402,8 +416,25 @@ static void prv_log_save(eMemfaultPlatformLogLevel level, const void *log, size_
402416 }
403417
404418 bool log_written = false;
405- const size_t truncated_log_len = MEMFAULT_MIN (log_len , MEMFAULT_LOG_MAX_LINE_SAVE_LEN );
406- const size_t bytes_needed = sizeof (sMfltRamLogEntry ) + truncated_log_len ;
419+ #if MEMFAULT_LOG_TIMESTAMPS_ENABLE
420+ sMemfaultCurrentTime timestamp ;
421+ const bool timestamped = memfault_platform_time_get_current (& timestamp );
422+ uint32_t timestamp_val ; // forward declaration for sizeof()
423+ const size_t timestamped_len = timestamped ? sizeof (timestamp_val ) : 0 ;
424+ #else
425+ const bool timestamped = false;
426+ const size_t timestamped_len = 0 ;
427+ #endif
428+
429+ // maximum msg length is truncated by timestamp, when enabled and valid.
430+ const size_t max_log_msg_len = MEMFAULT_LOG_MAX_LINE_SAVE_LEN - timestamped_len ;
431+
432+ const size_t truncated_log_len = MEMFAULT_MIN (log_len , max_log_msg_len );
433+ // total log length for the log entry .len field includes the timestamp.
434+ const uint8_t total_log_len = (uint8_t )(truncated_log_len + timestamped_len );
435+ // circular buffer space needed includes the metadata (hdr + len) and msg
436+ const size_t bytes_needed = sizeof (sMfltRamLogEntry ) + total_log_len ;
437+
407438 if (should_lock ) {
408439 memfault_lock ();
409440 }
@@ -413,10 +444,16 @@ static void prv_log_save(eMemfaultPlatformLogLevel level, const void *log, size_
413444 if (space_free ) {
414445 s_memfault_ram_logger .recorded_msg_count ++ ;
415446 sMfltRamLogEntry entry = {
416- .len = ( uint8_t ) truncated_log_len ,
417- .hdr = prv_build_header ( level , log_type ) ,
447+ .hdr = prv_build_header ( level , log_type , timestamped ) ,
448+ .len = total_log_len ,
418449 };
419450 memfault_circular_buffer_write (circ_bufp , & entry , sizeof (entry ));
451+ #if MEMFAULT_LOG_TIMESTAMPS_ENABLE
452+ if (timestamped ) {
453+ timestamp_val = timestamp .info .unix_timestamp_secs ;
454+ memfault_circular_buffer_write (circ_bufp , & timestamp_val , sizeof (timestamp_val ));
455+ }
456+ #endif
420457 memfault_circular_buffer_write (circ_bufp , log , truncated_log_len );
421458 log_written = true;
422459 } else {
0 commit comments