├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── Cross.toml ├── License.txt ├── README.md ├── VERSION ├── clippy.toml ├── memfault-ssf ├── Cargo.toml ├── License.txt ├── README.md ├── VERSION ├── src │ ├── envelope.rs │ ├── lib.rs │ ├── mailbox.rs │ ├── msg_mailbox.rs │ ├── scheduler.rs │ ├── scheduler │ │ └── job.rs │ ├── service_jig.rs │ ├── service_manager.rs │ ├── service_mock.rs │ ├── service_thread.rs │ ├── shared_service_thread.rs │ ├── stats.rs │ ├── stats │ │ └── aggregator.rs │ └── system_messages.rs └── tests │ └── message_mailbox.rs ├── memfaultc-sys ├── Cargo.toml ├── License.txt ├── README.md ├── VERSION ├── build.rs ├── libmemfaultc │ ├── .clang-format │ ├── .gitignore │ └── src │ │ ├── crash.c │ │ ├── swupdate.c │ │ └── systemd.c └── src │ ├── coredump.rs │ ├── lib.rs │ ├── swupdate.rs │ ├── systemd.rs │ └── systemd_mock.rs ├── memfaultd.init ├── memfaultd.service └── memfaultd ├── Cargo.toml ├── DEVELOPMENT.md ├── License.txt ├── README.md ├── VERSION ├── benches ├── log_level_mapper.rs └── logs_to_metrics.rs ├── build.rs ├── builtin.conf ├── memfaultd.conf └── src ├── bin ├── memfault-core-handler.rs ├── memfaultctl.rs ├── memfaultd.rs └── mfw.rs ├── cli ├── cargs.rs ├── memfault_core_handler │ ├── arch.rs │ ├── auxv.rs │ ├── core_elf_memfault_note.rs │ ├── core_elf_note.rs │ ├── core_reader.rs │ ├── core_transformer.rs │ ├── core_writer.rs │ ├── elf_utils.rs │ ├── find_dynamic.rs │ ├── find_elf_headers.rs │ ├── find_stack.rs │ ├── fixtures │ │ ├── elf-core-runtime-ld-paths.elf │ │ ├── sample_note.bin │ │ └── simple_executable │ │ │ ├── README.md │ │ │ ├── libc_ehframe.elf │ │ │ ├── simple_exe.c │ │ │ ├── simple_exe.elf │ │ │ └── simple_exe_core.elf │ ├── log_wrapper.rs │ ├── memory_range.rs │ ├── mod.rs │ ├── procfs.rs │ ├── r_debug.rs │ ├── snapshots │ │ ├── memfaultd__cli__memfault_core_handler__core_elf_memfault_note__test__serialize_debug_data.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_elf_memfault_note__test__serialize_metadata_as_map@app_logs.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_elf_memfault_note__test__serialize_metadata_as_map@kernel_selection.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_elf_memfault_note__test__serialize_metadata_as_map@threads.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_elf_note__test__iterate_elf_notes_with_fixture.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_transformer__test__transform@kernel_selection.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_transformer__test__transform@threads_32k.snap │ │ ├── memfaultd__cli__memfault_core_handler__core_transformer__test__transform@threads_32k_no_filter_support.snap │ │ ├── memfaultd__cli__memfault_core_handler__elf_utils__test__get_build_id.snap │ │ ├── memfaultd__cli__memfault_core_handler__elf_utils__test__section_header_read.snap │ │ ├── memfaultd__cli__memfault_core_handler__elf_utils__test__section_name_read.snap │ │ ├── memfaultd__cli__memfault_core_handler__find_dynamic__test__find_dynamic_linker_ranges.snap │ │ └── memfaultd__cli__memfault_core_handler__log_wrapper__test__log_saving.snap │ ├── stack_unwinder │ │ ├── eh_frame_finder.rs │ │ ├── mod.rs │ │ ├── snapshots │ │ │ └── memfaultd__cli__memfault_core_handler__stack_unwinder__unwind_handler__test__unwind_stack.snap │ │ ├── stacktrace_format.rs │ │ ├── unwind_handler.rs │ │ └── unwinder.rs │ └── test_utils.rs ├── memfault_watch │ ├── buffer.rs │ └── mod.rs ├── memfaultctl │ ├── add_battery_reading.rs │ ├── config_file.rs │ ├── coredump.rs │ ├── export.rs │ ├── mod.rs │ ├── report_sync.rs │ ├── session.rs │ ├── sync.rs │ ├── write_attributes.rs │ └── write_metrics.rs ├── memfaultd.rs ├── memfaultd_client.rs ├── mod.rs ├── show_settings.rs ├── snapshots │ └── memfaultd__cli__show_settings__tests__test.snap └── version.rs ├── collectd ├── collectd_handler.rs ├── fixtures │ ├── sample-with-null.json │ ├── sample1.json │ ├── statsd-counter-first-seen.json │ └── statsd-counter.json ├── mod.rs ├── payload.rs └── snapshots │ ├── memfaultd__collectd__collectd_handler__tests__drops_cpu_metrics_when_builtin_system_metrics_are_enabled.snap │ ├── memfaultd__collectd__collectd_handler__tests__handle_push.snap │ ├── memfaultd__collectd__payload__tests__sample-with-null.snap │ ├── memfaultd__collectd__payload__tests__sample1.snap │ ├── memfaultd__collectd__payload__tests__statsd-counter-first-seen.snap │ └── memfaultd__collectd__payload__tests__statsd-counter.snap ├── config ├── config_file.rs ├── device_config.rs ├── device_info.rs ├── mod.rs ├── snapshots │ ├── memfaultd__config__config_file__test__empty_object.snap │ ├── memfaultd__config__config_file__test__log_filters.snap │ ├── memfaultd__config__config_file__test__metrics_config.snap │ ├── memfaultd__config__config_file__test__set_and_write_bool_to_runtime_config@empty_object.snap │ ├── memfaultd__config__config_file__test__set_and_write_bool_to_runtime_config@no_file.snap │ ├── memfaultd__config__config_file__test__set_and_write_bool_to_runtime_config@other_key.snap │ ├── memfaultd__config__config_file__test__syslog.snap │ ├── memfaultd__config__config_file__test__with_connectivity_monitor.snap │ ├── memfaultd__config__config_file__test__with_coredump_capture_strategy_threads.snap │ ├── memfaultd__config__config_file__test__with_log_to_metrics_rules.snap │ ├── memfaultd__config__config_file__test__with_partial_logs.snap │ ├── memfaultd__config__config_file__test__with_sessions.snap │ └── memfaultd__config__config_file__test__without_coredump_compression.snap ├── test-config │ ├── empty_object.json │ ├── log_filters.json │ ├── metrics_config.json │ ├── syslog.json │ ├── with_connectivity_monitor.json │ ├── with_coredump_capture_strategy_threads.json │ ├── with_invalid_path.json │ ├── with_invalid_swt_swv.json │ ├── with_log_to_metrics_rules.json │ ├── with_partial_logs.json │ ├── with_sessions.json │ ├── with_sessions_invalid_metric_name.json │ ├── with_sessions_invalid_session_name.json │ └── without_coredump_compression.json └── utils.rs ├── coredump └── mod.rs ├── fluent_bit ├── decode_time.rs └── mod.rs ├── http_server ├── handler.rs ├── mod.rs ├── request_bodies.rs ├── server.rs └── utils.rs ├── lib.rs ├── logs ├── completed_log.rs ├── headroom.rs ├── journald_parser.rs ├── journald_provider.rs ├── levels.rs ├── log_collector.rs ├── log_entry.rs ├── log_file.rs ├── log_filter.rs ├── log_level_mapper.rs ├── log_to_metrics.rs ├── messages.rs ├── mod.rs ├── recovery.rs ├── snapshots │ ├── memfaultd__logs__fluent_bit_adapter__tests__fluent_bit_adapter.snap │ ├── memfaultd__logs__journald_parser__test__from_raw_journal_entry.snap │ ├── memfaultd__logs__journald_parser__test__journal_happy_path.snap │ ├── memfaultd__logs__journald_provider__test__extra_attr.snap │ ├── memfaultd__logs__journald_provider__test__no_extra_attr.snap │ ├── memfaultd__logs__log_entry__tests__extra_attribute_filter.snap │ ├── memfaultd__logs__log_entry__tests__extra_key.snap │ ├── memfaultd__logs__log_entry__tests__multi_key_match.snap │ ├── memfaultd__logs__log_entry__tests__only_message.snap │ ├── memfaultd__logs__log_filter__tests__earlier_rules_take_priority-metrics.snap │ ├── memfaultd__logs__log_filter__tests__earlier_rules_take_priority.snap │ ├── memfaultd__logs__log_filter__tests__filter_rules.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_applied_before_filter_rules-metrics.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_applied_before_filter_rules.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_config-metrics.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_config.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_matches_filter_rules-metrics.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_matches_filter_rules.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_with_service_and_priority-metrics.snap │ ├── memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_with_service_and_priority.snap │ ├── memfaultd__logs__log_filter__tests__logs_to_metrics_with_dynamic_counters-metrics.snap │ ├── memfaultd__logs__log_filter__tests__logs_to_metrics_with_dynamic_counters.snap │ ├── memfaultd__logs__log_filter__tests__multiple_log_lines-metrics.snap │ ├── memfaultd__logs__log_filter__tests__multiple_log_lines.snap │ ├── memfaultd__logs__log_filter__tests__multiple_log_lines_mixed_rules-metrics.snap │ ├── memfaultd__logs__log_filter__tests__multiple_log_lines_mixed_rules.snap │ ├── memfaultd__logs__log_filter__tests__multiple_rules_with_extra_fields-metrics.snap │ ├── memfaultd__logs__log_filter__tests__multiple_rules_with_extra_fields.snap │ ├── memfaultd__logs__log_filter__tests__one_line_one_rule_matching-metrics.snap │ ├── memfaultd__logs__log_filter__tests__one_line_one_rule_matching.snap │ ├── memfaultd__logs__log_filter__tests__simple_logs_to_metrics-metrics.snap │ ├── memfaultd__logs__log_filter__tests__simple_logs_to_metrics.snap │ ├── memfaultd__logs__log_filter__tests__simple_with_extra_fields-metrics.snap │ ├── memfaultd__logs__log_filter__tests__simple_with_extra_fields.snap │ ├── memfaultd__logs__log_filter__tests__test_default_rules-metrics.snap │ ├── memfaultd__logs__log_filter__tests__test_default_rules.snap │ ├── memfaultd__logs__syslog__tests__kernel_panic_rfc_3164.snap │ ├── memfaultd__logs__syslog__tests__multiple_messages.snap │ ├── memfaultd__logs__syslog__tests__system_started_rfc_3164.snap │ └── memfaultd__logs__syslog__tests__system_started_rfc_5424.snap └── syslog.rs ├── mar ├── chunks.rs ├── chunks │ ├── chunk.rs │ ├── chunk_header.rs │ ├── chunk_message.rs │ ├── chunk_wrapper.rs │ └── crc_padded_stream.rs ├── clean.rs ├── export.rs ├── export_format.rs ├── manifest.rs ├── mar_entry.rs ├── mar_entry_builder.rs ├── mod.rs ├── snapshots │ ├── memfaultd__mar__clean__test__deletes_mar_entry_when_over_max_count.snap │ ├── memfaultd__mar__clean__test__keeps_mar_entry_when_max_age_is_zero.snap │ ├── memfaultd__mar__clean__test__keeps_mar_entry_within_max_age.snap │ ├── memfaultd__mar__clean__test__keeps_recent_mar_entry.snap │ ├── memfaultd__mar__clean__test__keeps_recent_unfinished_mar_entry.snap │ ├── memfaultd__mar__clean__test__max_entries_0.snap │ ├── memfaultd__mar__clean__test__max_entries_equal.snap │ ├── memfaultd__mar__clean__test__max_entries_greater_than.snap │ ├── memfaultd__mar__clean__test__max_entries_less_than.snap │ ├── memfaultd__mar__clean__test__removes_entries_exceeding_max_total_size_by_age.snap │ ├── memfaultd__mar__clean__test__removes_entries_exceeding_min_headroom_size_by_age.snap │ ├── memfaultd__mar__clean__test__removes_mar_entry_exceeding_max_age.snap │ ├── memfaultd__mar__clean__test__removes_mar_entry_exceeding_max_total_size.snap │ ├── memfaultd__mar__clean__test__removes_mar_entry_exceeding_min_headroom.snap │ ├── memfaultd__mar__clean__test__removes_mar_entry_exceeding_min_headroom_inodes.snap │ ├── memfaultd__mar__clean__test__removes_oldest_mar_entry_exceeding_max_total_size_when_multiple.snap │ ├── memfaultd__mar__clean__test__removes_unfinished_mar_entry_exceeding_max_total_size.snap │ ├── memfaultd__mar__manifest__tests__attributes.snap │ ├── memfaultd__mar__manifest__tests__coredump-gzip.snap │ ├── memfaultd__mar__manifest__tests__coredump-none.snap │ ├── memfaultd__mar__manifest__tests__device_config.snap │ ├── memfaultd__mar__manifest__tests__elf_coredump.snap │ ├── memfaultd__mar__manifest__tests__heartbeat.snap │ ├── memfaultd__mar__manifest__tests__heartbeat_with_duration.snap │ ├── memfaultd__mar__manifest__tests__log-none.snap │ ├── memfaultd__mar__manifest__tests__log-zlib.snap │ ├── memfaultd__mar__manifest__tests__metric_report.snap │ ├── memfaultd__mar__manifest__tests__reboot.snap │ ├── memfaultd__mar__manifest__tests__serialization_of_custom_reboot.snap │ ├── memfaultd__mar__manifest__tests__serialization_of_custom_unexpected_reboot.snap │ ├── memfaultd__mar__manifest__tests__serialization_of_device_attributes.snap │ ├── memfaultd__mar__manifest__tests__serialization_of_device_configc.snap │ ├── memfaultd__mar__manifest__tests__serialization_of_linux_heartbeat.snap │ └── memfaultd__mar__manifest__tests__serialization_of_reboot.snap ├── test-manifests │ ├── attributes.json │ ├── device_config.json │ ├── elf_coredump.json │ ├── heartbeat.json │ ├── heartbeat_with_duration.json │ ├── log.json │ ├── metric_report.json │ └── reboot.json ├── test_utils.rs └── upload.rs ├── memfaultd.rs ├── metrics ├── battery │ ├── battery_monitor.rs │ ├── battery_reading_handler.rs │ ├── mod.rs │ └── snapshots │ │ ├── memfaultd__metrics__battery__battery_reading_handler__tests__charging_then_discharging.snap │ │ ├── memfaultd__metrics__battery__battery_reading_handler__tests__handle_push.snap │ │ ├── memfaultd__metrics__battery__battery_reading_handler__tests__non_integer_percentages.snap │ │ └── memfaultd__metrics__battery__battery_reading_handler__tests__nonconsecutive_discharges.snap ├── connectivity │ ├── connectivity_monitor.rs │ ├── mod.rs │ ├── report_sync_event_handler.rs │ └── snapshots │ │ ├── memfaultd__metrics__connectivity__connectivity_monitor__tests__fully_disconnected.snap │ │ ├── memfaultd__metrics__connectivity__connectivity_monitor__tests__half_connected_half_disconnected.snap │ │ ├── memfaultd__metrics__connectivity__connectivity_monitor__tests__while_connected.snap │ │ ├── memfaultd__metrics__connectivity__report_sync_event_handler__tests__handle_multiple_sync_events.snap │ │ ├── memfaultd__metrics__connectivity__report_sync_event_handler__tests__handle_sync_failure.snap │ │ └── memfaultd__metrics__connectivity__report_sync_event_handler__tests__handle_sync_success.snap ├── core_metrics.rs ├── crashfree_interval.rs ├── hrt │ ├── mod.rs │ ├── report.rs │ ├── schema.rs │ └── snapshots │ │ ├── memfaultd__metrics__hrt__report__tests__build_hrt_report.snap │ │ ├── memfaultd__metrics__hrt__schema__test__cdr_write-2.snap │ │ ├── memfaultd__metrics__hrt__schema__test__cdr_write.snap │ │ ├── memfaultd__metrics__hrt__schema__test__counter.snap │ │ ├── memfaultd__metrics__hrt__schema__test__gauge.snap │ │ ├── memfaultd__metrics__hrt__schema__test__histogram.snap │ │ └── memfaultd__metrics__hrt__schema__test__serialization.snap ├── internal_metrics.rs ├── messages.rs ├── metric_reading.rs ├── metric_report.rs ├── metric_report_manager.rs ├── metric_string_key.rs ├── metric_value.rs ├── metrics_event_handler.rs ├── mod.rs ├── session_event_handler.rs ├── session_name.rs ├── snapshots │ ├── memfaultd__metrics__crashfree_interval__tests__process_crash_counter.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_1.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_2.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_3.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_4.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_5.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_6.snap │ ├── memfaultd__metrics__metric_report__tests__heartbeat_report_7.snap │ ├── memfaultd__metrics__metric_report__tests__overwrite_previous_reading.snap │ ├── memfaultd__metrics__metric_report__tests__session_report_1.snap │ ├── memfaultd__metrics__metric_report__tests__session_report_2.snap │ ├── memfaultd__metrics__metric_report__tests__session_report_3.snap │ ├── memfaultd__metrics__metric_report__tests__session_report_4.snap │ ├── memfaultd__metrics__metric_report__tests__session_report_5.snap │ ├── memfaultd__metrics__metric_report__tests__session_report_6.snap │ ├── memfaultd__metrics__metric_report_manager__tests__daily-heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.daily_heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.test-session-all-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.test-session-some-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.daily_heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.test-session-all-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.test-session-some-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.daily_heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.test-session-all-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.test-session-some-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.daily_heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.test-session-all-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.test-session-some-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.daily_heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.heartbeat.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.test-session-all-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.test-session-some-metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_report_1.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_report_2.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_report_3.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_report_4.snap │ ├── memfaultd__metrics__metric_report_manager__tests__heartbeat_report_5.snap │ ├── memfaultd__metrics__metric_report_manager__tests__hrt_when_enabled.snap │ ├── memfaultd__metrics__metric_report_manager__tests__process_metrics_metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__start_session_twice.snap │ ├── memfaultd__metrics__metric_report_manager__tests__system_and_process_metrics_metrics.snap │ ├── memfaultd__metrics__metric_report_manager__tests__test-session.snap │ ├── memfaultd__metrics__metrics_event_handler__test__handle_request.snap │ ├── memfaultd__metrics__session_event_handler__tests__end_with_metrics.snap │ ├── memfaultd__metrics__session_event_handler__tests__start_then_stop.snap │ ├── memfaultd__metrics__session_event_handler__tests__start_twice_without_stop_session.snap │ ├── memfaultd__metrics__session_event_handler__tests__start_with_metrics.snap │ └── memfaultd__metrics__session_event_handler__tests__start_without_stop_session.snap ├── statsd_server │ ├── mod.rs │ └── snapshots │ │ ├── memfaultd__metrics__statsd_server__test__test_counter_aggregation.snap │ │ ├── memfaultd__metrics__statsd_server__test__test_counter_and_gauge_aggregation.snap │ │ ├── memfaultd__metrics__statsd_server__test__test_counter_and_legacy_gauge_aggregation.snap │ │ ├── memfaultd__metrics__statsd_server__test__test_histogram_aggregation.snap │ │ ├── memfaultd__metrics__statsd_server__test__test_legacy_gauge_aggregation.snap │ │ ├── memfaultd__metrics__statsd_server__test__test_simple.snap │ │ └── memfaultd__metrics__statsd_server__test__test_simple_dashes.snap ├── system_metrics │ ├── cpu.rs │ ├── disk.rs │ ├── disk_space.rs │ ├── diskstats.rs │ ├── memory.rs │ ├── mod.rs │ ├── network_interfaces.rs │ ├── processes.rs │ ├── snapshots │ │ ├── memfaultd__metrics__system_metrics__cpu__test__basic_delta_a_b_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__cpu__test__basic_delta_b_c_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__cpu__test__test_basic_line.snap │ │ ├── memfaultd__metrics__system_metrics__disk__test__get_disk_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__disk_space__test__initialize_and_calc_disk_space_for_mounts-2.snap │ │ ├── memfaultd__metrics__system_metrics__disk_space__test__initialize_and_calc_disk_space_for_mounts.snap │ │ ├── memfaultd__metrics__system_metrics__diskstats__test__basic_diskstats_calc.snap │ │ ├── memfaultd__metrics__system_metrics__diskstats__test__basic_diskstats_line.snap │ │ ├── memfaultd__metrics__system_metrics__diskstats__test__from_qemu.snap │ │ ├── memfaultd__metrics__system_metrics__memory__test__get_memory_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__memory__test__get_memory_metrics_no_memavailable.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__basic_delta_a_b_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__basic_delta_b_c_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__different_interfaces_a_c_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__different_interfaces_b_d_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__eth0.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__with_overflow_a_b_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__with_overflow_b_c_metrics.snap │ │ ├── memfaultd__metrics__system_metrics__network_interfaces__test__wlan1.snap │ │ ├── memfaultd__metrics__system_metrics__processes__tests__process_metrics_auto_false.snap │ │ ├── memfaultd__metrics__system_metrics__processes__tests__process_metrics_auto_true.snap │ │ ├── memfaultd__metrics__system_metrics__processes__tests__simple_cpu_delta_metrics.snap │ │ └── memfaultd__metrics__system_metrics__thermal__tests__read_thermal_zone_temp.snap │ └── thermal.rs └── timeseries │ └── mod.rs ├── mmc.rs ├── network ├── client.rs ├── mod.rs ├── requests.rs └── snapshots │ ├── memfaultd__network__requests__test__device_config.snap │ ├── memfaultd__network__requests__test__device_config_missing_upload_start.snap │ └── memfaultd__network__requests__test__prepare_upload_serialization.snap ├── reboot ├── mod.rs ├── reason.rs └── reason_codes.rs ├── retriable_error.rs ├── service_manager ├── default.rs ├── mod.rs └── systemd.rs ├── swupdate ├── config.rs └── mod.rs ├── test_utils.rs ├── test_utils ├── test_connection_checker.rs └── test_instant.rs └── util ├── can_connect.rs ├── circular_queue.rs ├── die.rs ├── disk_backed.rs ├── disk_size.rs ├── etc_os_release.rs ├── fs.rs ├── io.rs ├── ipc.rs ├── math.rs ├── mem.rs ├── mod.rs ├── output_arg.rs ├── path.rs ├── patterns.rs ├── persistent_rate_limiter.rs ├── pid_file.rs ├── rate_limiter.rs ├── serialization ├── datetime_to_rfc3339.rs ├── float_to_datetime.rs ├── float_to_duration.rs ├── kib_to_usize.rs ├── milliseconds_to_duration.rs ├── mod.rs ├── number_to_compression.rs ├── optional_datetime_to_rfc3339.rs ├── optional_milliseconds_to_duration.rs ├── seconds_to_duration.rs └── sorted_map.rs ├── string.rs ├── system.rs ├── task.rs ├── tcp_server.rs ├── time_measure.rs ├── wildcard_pattern.rs ├── zip.rs └── zip_dir.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "memfaultd", 5 | "memfaultc-sys", 6 | "memfault-ssf" 7 | ] 8 | resolver = "2" 9 | 10 | [profile.release] 11 | # We do not handle FFI unwinding so we need to keep panic abort for now. 12 | panic="abort" 13 | opt-level = "z" 14 | 15 | [profile.dev] 16 | panic="abort" 17 | -------------------------------------------------------------------------------- /Cross.toml: -------------------------------------------------------------------------------- 1 | [target.aarch64-unknown-linux-gnu] 2 | pre-build = [ 3 | "dpkg --add-architecture $CROSS_DEB_ARCH", 4 | "apt-get update", 5 | "apt-get install --assume-yes libsystemd-dev:$CROSS_DEB_ARCH libconfig-dev:$CROSS_DEB_ARCH" 6 | ] 7 | 8 | [target.x86_64-unknown-linux-gnu] 9 | pre-build = [ 10 | "dpkg --add-architecture $CROSS_DEB_ARCH", 11 | "apt-get update", 12 | "apt-get install --assume-yes libsystemd-dev:$CROSS_DEB_ARCH libconfig-dev:$CROSS_DEB_ARCH" 13 | ] 14 | 15 | [target.armv7-unknown-linux-gnueabihf] 16 | pre-build = [ 17 | "dpkg --add-architecture $CROSS_DEB_ARCH", 18 | "apt-get update", 19 | "apt-get install --assume-yes libsystemd-dev:$CROSS_DEB_ARCH libconfig-dev:$CROSS_DEB_ARCH" 20 | ] 21 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 - Present, Memfault 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code or in binary form must reproduce 8 | the above copyright notice, this list of conditions and the following 9 | disclaimer in the documentation and/or other materials provided with the 10 | distribution. 11 | 12 | 2. Neither the name of Memfault nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | 3. This software, with or without modification, must only be used with 17 | the Memfault services and integrated with the Memfault server. 18 | 19 | 4. Any software provided in binary form under this license must not be 20 | reverse engineered, decompiled, modified and/or disassembled. 21 | 22 | THIS SOFTWARE IS PROVIDED BY MEMFAULT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 24 | NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | SHALL MEMFAULT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `memfaultd` 2 | 3 | `memfaultd` is a daemon that runs on your device and collects crash reports and 4 | metrics. It is the core of the 5 | [Memfault Linux SDK](https://github.com/memfault/memfault-linux-sdk/blob/kirkstone/README.md). 6 | 7 | ## Overview 8 | 9 | `memfaultd` supports several features to help you maintain and debug your fleet 10 | of devices: 11 | 12 | - **Crash reporting**: When your device crashes, `memfaultd` collects a crash 13 | report from 14 | [Linux Coredumps](https://man7.org/linux/man-pages/man5/core.5.html). For more 15 | information, see the 16 | [Coredumps documentation](https://docs.memfault.com/docs/linux/coredumps). 17 | 18 | - **Metrics**: `memfaultd` collects metrics from your device and uploads them to 19 | Memfault. For more information, see the 20 | [Metrics documentation](https://docs.memfault.com/docs/linux/metrics). 21 | 22 | - **Reboot reason tracking**: `memfaultd` detects various reboot reasons from 23 | the system and reports them to the Memfault Dashboard. Users can also provide 24 | a specific reboot reason before restarting the device. For more information, 25 | see the 26 | [Reboot Reason Tracking documentation](https://docs.memfault.com/docs/linux/reboot-reason-tracking). 27 | 28 | - **OTA Updates**: `memfaultd` supports [SWUpdate](https://swupdate.org/) out of 29 | the box and is able to configure it to talk to our hawkBit DDI-compatible 30 | endpoint. For more information, see the 31 | [Linux OTA Management documentation](https://docs.memfault.com/docs/linux/ota). 32 | 33 | - **Logging**: `memfaultd` collects logs from your system. For more information, 34 | see the [Logging documentation](https://docs.memfault.com/docs/linux/logging). 35 | 36 | And much more! [Register](https://app.memfault.com/register) and get started 37 | today! 38 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | BUILD ID: 3112275 2 | GIT COMMIT: eaa113a284 3 | VERSION: 1.21.1 4 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | allow-unwrap-in-tests = true 2 | -------------------------------------------------------------------------------- /memfault-ssf/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memfault-ssf" 3 | version = "1.21.1" 4 | edition = "2021" 5 | description = "Supporting crate for the Memfault memfaultd embedded Linux agent" 6 | homepage = "https://github.com/memfault/memfaultd" 7 | documentation = "https://docs.memfault.com/" 8 | license-file = "License.txt" 9 | readme = "README.md" 10 | repository = "https://github.com/memfault/memfaultd" 11 | 12 | [dependencies] 13 | futures = "0.3.31" 14 | log = "0.4" 15 | tokio = { version = "1.43.0", features = ["sync", "macros", "rt", "net"] } 16 | 17 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 18 | -------------------------------------------------------------------------------- /memfault-ssf/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 - Present, Memfault 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code or in binary form must reproduce 8 | the above copyright notice, this list of conditions and the following 9 | disclaimer in the documentation and/or other materials provided with the 10 | distribution. 11 | 12 | 2. Neither the name of Memfault nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | 3. This software, with or without modification, must only be used with 17 | the Memfault services and integrated with the Memfault server. 18 | 19 | 4. Any software provided in binary form under this license must not be 20 | reverse engineered, decompiled, modified and/or disassembled. 21 | 22 | THIS SOFTWARE IS PROVIDED BY MEMFAULT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 24 | NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | SHALL MEMFAULT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /memfault-ssf/README.md: -------------------------------------------------------------------------------- 1 | # `memfault-ssf` 2 | 3 | Internal crate for use by the 4 | [`memfaultd`](https://github.com/memfault/memfaultd/) crate, not for general 5 | use. 6 | -------------------------------------------------------------------------------- /memfault-ssf/VERSION: -------------------------------------------------------------------------------- 1 | BUILD ID: 3112275 2 | GIT COMMIT: eaa113a284 3 | VERSION: 1.21.1 4 | -------------------------------------------------------------------------------- /memfault-ssf/src/service_jig.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::sync::mpsc::Receiver; 5 | 6 | use crate::{Envelope, Mailbox, Service}; 7 | 8 | /// The ServiceJig allows you to create a mailbox for a service and control when 9 | /// messages will be processed. It does not use thread and is specifically well 10 | /// suited for unit tests. 11 | pub struct ServiceJig { 12 | pub mailbox: Mailbox, 13 | service: S, 14 | receiver: Receiver>, 15 | } 16 | 17 | impl ServiceJig { 18 | pub fn prepare(service: S) -> Self { 19 | let (mailbox, receiver) = Mailbox::create(); 20 | 21 | ServiceJig { 22 | service, 23 | receiver, 24 | mailbox, 25 | } 26 | } 27 | 28 | /// Process all waiting messages 29 | pub fn process_all(&mut self) { 30 | let iter = self.receiver.try_iter(); 31 | for mut m in iter { 32 | let _x = m.deliver_to(&mut self.service); 33 | } 34 | } 35 | 36 | pub fn get_service(&self) -> &S { 37 | &self.service 38 | } 39 | 40 | pub fn get_service_mut(&mut self) -> &mut S { 41 | &mut self.service 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /memfault-ssf/src/service_mock.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::sync::mpsc::Receiver; 5 | 6 | use crate::{Message, MsgMailbox}; 7 | 8 | /// The ServiceMock allows you to mock a service processing messages of a specific type. 9 | pub struct ServiceMock { 10 | pub mbox: MsgMailbox, 11 | receiver: Receiver, 12 | } 13 | 14 | impl ServiceMock { 15 | pub fn new() -> Self { 16 | let (mbox, receiver) = MsgMailbox::mock(); 17 | Self { mbox, receiver } 18 | } 19 | 20 | pub fn new_bounded(channel_size: usize) -> Self { 21 | let (mbox, receiver) = MsgMailbox::bounded_mock(channel_size); 22 | Self { mbox, receiver } 23 | } 24 | 25 | pub fn take_messages(&mut self) -> Vec { 26 | self.receiver.try_iter().collect() 27 | } 28 | } 29 | 30 | impl Default for ServiceMock { 31 | fn default() -> Self { 32 | Self::new() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /memfault-ssf/src/stats.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::time::Duration; 5 | 6 | mod aggregator; 7 | pub use aggregator::*; 8 | 9 | pub struct DeliveryStats { 10 | /// How long message was in queue before being delivered 11 | pub queued: Duration, 12 | /// Time to process message (excluding queueing time) 13 | pub processing: Duration, 14 | } 15 | -------------------------------------------------------------------------------- /memfault-ssf/src/stats/aggregator.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::{fmt::Display, time::Duration}; 5 | 6 | use super::DeliveryStats; 7 | 8 | #[derive(Debug)] 9 | pub struct StatsAggregator { 10 | count: usize, 11 | max_queueing: Duration, 12 | max_processing: Duration, 13 | total_processing: Duration, 14 | } 15 | 16 | impl StatsAggregator { 17 | pub fn new() -> Self { 18 | StatsAggregator { 19 | count: 0, 20 | max_queueing: Duration::ZERO, 21 | max_processing: Duration::ZERO, 22 | total_processing: Duration::ZERO, 23 | } 24 | } 25 | pub fn add(&mut self, stats: &DeliveryStats) { 26 | self.count += 1; 27 | self.total_processing += stats.processing; 28 | self.max_queueing = self.max_queueing.max(stats.queued); 29 | self.max_processing = self.max_processing.max(stats.processing); 30 | } 31 | } 32 | 33 | impl Default for StatsAggregator { 34 | fn default() -> Self { 35 | StatsAggregator::new() 36 | } 37 | } 38 | 39 | impl Display for StatsAggregator { 40 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 41 | if self.count > 0 { 42 | f.write_fmt(format_args!( 43 | "Calls: {} Max Queueing: {} Processing (avg/max): {}/{} ", 44 | self.count, 45 | self.max_queueing.as_millis(), 46 | (self.total_processing / (self.count as u32)).as_millis(), 47 | self.max_processing.as_millis(), 48 | )) 49 | } else { 50 | f.write_fmt(format_args!("Calls: 0")) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /memfault-ssf/src/system_messages.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::{Handler, Message, Service}; 5 | 6 | /// The `ShutdownServiceMessage` is supported by all services. It terminates the 7 | /// thread. No other message in the queue will be processed. 8 | /// The service will receive this message and can do something before shutting 9 | /// down. 10 | pub struct ShutdownServiceMessage {} 11 | impl Message for ShutdownServiceMessage { 12 | type Reply = (); 13 | } 14 | 15 | impl Handler for S { 16 | fn deliver(&mut self, _m: ShutdownServiceMessage) {} 17 | } 18 | 19 | /// The `PingMessage` is supported by all services. It allows the caller to 20 | /// verify that the service is still running and that it has processed its 21 | /// queue. 22 | pub struct PingMessage {} 23 | impl Message for PingMessage { 24 | type Reply = (); 25 | } 26 | 27 | impl Handler for S { 28 | fn deliver(&mut self, _m: PingMessage) {} 29 | } 30 | -------------------------------------------------------------------------------- /memfault-ssf/tests/message_mailbox.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use memfault_ssf::{self, Handler, MailboxError, Message, MsgMailbox, Service, ServiceJig}; 5 | 6 | struct MyService { 7 | count: usize, 8 | } 9 | 10 | impl Service for MyService { 11 | fn name(&self) -> &str { 12 | "MyService" 13 | } 14 | } 15 | 16 | struct MyMessage; 17 | impl Message for MyMessage { 18 | type Reply = (); 19 | } 20 | 21 | impl Handler for MyService { 22 | fn deliver(&mut self, _m: MyMessage) { 23 | self.count += 1; 24 | } 25 | } 26 | 27 | struct OtherService { 28 | mailbox: MsgMailbox, 29 | } 30 | 31 | impl Service for OtherService { 32 | fn name(&self) -> &str { 33 | "OtherService" 34 | } 35 | } 36 | 37 | struct OtherMessage(); 38 | impl Message for OtherMessage { 39 | type Reply = Result<(), MailboxError>; 40 | } 41 | 42 | impl Handler for OtherService { 43 | fn deliver(&mut self, _m: OtherMessage) -> Result<(), MailboxError> { 44 | self.mailbox.send_and_forget(MyMessage) 45 | } 46 | } 47 | 48 | #[test] 49 | fn message_mailbox() { 50 | let mut service = ServiceJig::prepare(MyService { count: 0 }); 51 | let mut other = ServiceJig::prepare(OtherService { 52 | mailbox: service.mailbox.clone().into(), 53 | }); 54 | 55 | other.mailbox.send_and_forget(OtherMessage()).unwrap(); 56 | 57 | other.process_all(); 58 | service.process_all(); 59 | 60 | assert_eq!(service.get_service().count, 1); 61 | } 62 | -------------------------------------------------------------------------------- /memfaultc-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memfaultc-sys" 3 | version = "1.21.1" 4 | edition = "2021" 5 | autobins = false 6 | description = "Supporting crate for the Memfault memfaultd embedded Linux agent" 7 | homepage = "https://github.com/memfault/memfaultd" 8 | documentation = "https://docs.memfault.com/" 9 | license-file = "License.txt" 10 | readme = "README.md" 11 | repository = "https://github.com/memfault/memfaultd" 12 | 13 | [dependencies] 14 | libc = "0.2.138" 15 | 16 | [build-dependencies] 17 | cc = "1.0.95" 18 | pkg-config = "0.3" 19 | walkdir = "2" 20 | 21 | [features] 22 | default = [] 23 | coredump = [] 24 | systemd = [] 25 | swupdate = [] 26 | -------------------------------------------------------------------------------- /memfaultc-sys/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 - Present, Memfault 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code or in binary form must reproduce 8 | the above copyright notice, this list of conditions and the following 9 | disclaimer in the documentation and/or other materials provided with the 10 | distribution. 11 | 12 | 2. Neither the name of Memfault nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | 3. This software, with or without modification, must only be used with 17 | the Memfault services and integrated with the Memfault server. 18 | 19 | 4. Any software provided in binary form under this license must not be 20 | reverse engineered, decompiled, modified and/or disassembled. 21 | 22 | THIS SOFTWARE IS PROVIDED BY MEMFAULT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 24 | NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | SHALL MEMFAULT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /memfaultc-sys/README.md: -------------------------------------------------------------------------------- 1 | # `memfaultc-sys` 2 | 3 | Internal crate for use by the 4 | [`memfaultd`](https://github.com/memfault/memfaultd/) crate, not for general 5 | use. 6 | -------------------------------------------------------------------------------- /memfaultc-sys/VERSION: -------------------------------------------------------------------------------- 1 | BUILD ID: 3112275 2 | GIT COMMIT: eaa113a284 3 | VERSION: 1.21.1 4 | -------------------------------------------------------------------------------- /memfaultc-sys/libmemfaultc/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | --- 4 | Language: Cpp 5 | 6 | AlwaysBreakBeforeMultilineStrings: false 7 | ColumnLimit: '100' 8 | ContinuationIndentWidth: 2 9 | IndentPPDirectives: BeforeHash 10 | ... 11 | -------------------------------------------------------------------------------- /memfaultc-sys/libmemfaultc/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /.cache 3 | -------------------------------------------------------------------------------- /memfaultc-sys/libmemfaultc/src/crash.c: -------------------------------------------------------------------------------- 1 | //! @file 2 | //! 3 | //! Copyright (c) Memfault, Inc. 4 | //! See License.txt for details 5 | //! 6 | //! @brief 7 | //! 8 | 9 | #include 10 | 11 | void memfault_trigger_fp_exception(void) { 12 | int divisor = 0; 13 | // Triggers an illegal instruction on x86 - Floating Point Error on ARM 14 | printf("%i", 42 / divisor); 15 | } 16 | -------------------------------------------------------------------------------- /memfaultc-sys/src/coredump.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | extern "C" { 5 | pub fn memfault_trigger_fp_exception(); 6 | } 7 | -------------------------------------------------------------------------------- /memfaultc-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | // main functions 5 | 6 | #[cfg(feature = "coredump")] 7 | pub mod coredump; 8 | 9 | #[cfg(all(feature = "systemd", not(target_os = "macos")))] 10 | pub mod systemd; 11 | #[cfg(all(feature = "systemd", target_os = "macos"))] 12 | pub mod systemd_mock; 13 | 14 | #[cfg(all(feature = "systemd", target_os = "macos"))] 15 | pub use systemd_mock as systemd; 16 | 17 | #[cfg(feature = "swupdate")] 18 | pub mod swupdate; 19 | -------------------------------------------------------------------------------- /memfaultc-sys/src/swupdate.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use libc::c_char; 5 | 6 | #[repr(C)] 7 | pub struct MemfaultSwupdateCtx { 8 | pub base_url: *const c_char, 9 | 10 | pub software_version: *const c_char, 11 | pub software_type: *const c_char, 12 | pub hardware_version: *const c_char, 13 | pub device_id: *const c_char, 14 | pub project_key: *const c_char, 15 | 16 | pub input_file: *const c_char, 17 | pub output_file: *const c_char, 18 | } 19 | 20 | extern "C" { 21 | pub fn memfault_swupdate_generate_config(ctx: *const MemfaultSwupdateCtx) -> bool; 22 | } 23 | -------------------------------------------------------------------------------- /memfaultc-sys/src/systemd.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::ffi::c_int; 5 | 6 | use libc::{c_char, size_t}; 7 | 8 | #[allow(non_camel_case_types)] 9 | pub enum sd_journal {} 10 | 11 | extern "C" { 12 | pub fn memfaultd_restart_systemd_service_if_running(service_name: *const c_char) -> bool; 13 | pub fn memfaultd_get_systemd_bus_state() -> *const c_char; 14 | pub fn sd_journal_open(ret: *mut *mut sd_journal, flags: c_int) -> c_int; 15 | pub fn sd_journal_seek_tail(j: *mut sd_journal) -> c_int; 16 | pub fn sd_journal_previous(j: *mut sd_journal) -> c_int; 17 | pub fn sd_journal_next(j: *mut sd_journal) -> c_int; 18 | pub fn sd_journal_get_data( 19 | j: *mut sd_journal, 20 | field: *const c_char, 21 | data: *mut *mut u8, 22 | l: *mut size_t, 23 | ) -> c_int; 24 | pub fn sd_journal_enumerate_data( 25 | j: *mut sd_journal, 26 | data: *mut *mut u8, 27 | l: *mut size_t, 28 | ) -> c_int; 29 | pub fn sd_journal_get_fd(j: *mut sd_journal) -> c_int; 30 | pub fn sd_journal_process(j: *mut sd_journal) -> c_int; 31 | pub fn sd_journal_get_realtime_usec(j: *mut sd_journal, ret: *mut u64) -> c_int; 32 | pub fn sd_journal_get_cursor(j: *mut sd_journal, cursor: *mut *const c_char) -> c_int; 33 | pub fn sd_journal_seek_cursor(j: *mut sd_journal, cursor: *const c_char) -> c_int; 34 | pub fn sd_journal_add_match(j: *mut sd_journal, data: *const c_char, size: size_t) -> c_int; 35 | } 36 | -------------------------------------------------------------------------------- /memfaultd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=memfaultd daemon 3 | After=local-fs.target network.target dbus.service 4 | Before=swupdate.service collectd.service 5 | 6 | [Service] 7 | Type=forking 8 | PIDFile=/run/memfaultd.pid 9 | ExecStart=/usr/bin/memfaultd --daemonize 10 | # Wait for the PID file to be populated before returning 11 | ExecStartPost=/bin/sh -c "while [ $(cat /run/memfaultd.pid 2>/dev/null | wc -c) -eq 0 ]; do sleep 0.1; done" 12 | Restart=on-failure 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /memfaultd/DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | `memfaultd` build is controlled by Cargo. The `Cargo.toml` and `build.rs` 4 | control the rust build process and compile the few C files. 5 | 6 | ## Building outside Yocto 7 | 8 | ### Dependencies 9 | 10 | #### Debian/Ubuntu 11 | 12 | ```sh 13 | apt install libsystemd-dev libconfig-dev 14 | ``` 15 | 16 | #### macOS 17 | 18 | ```sh 19 | brew install pkg-config libconfig 20 | ``` 21 | 22 | (note: `libsystemd` is not available on macOS and the build system will not try 23 | to link it) 24 | 25 | ### Building 26 | 27 | ```sh 28 | cargo build 29 | ``` 30 | 31 | ## Building with Yocto 32 | 33 | Use the `docker/run.sh` script to run a docker container with all the required 34 | dependencies. Use the alias `b` to build the image. 35 | 36 | ## Running tests 37 | 38 | ### Unit tests 39 | 40 | Do this after running a build, inside the (cmake) build directory: 41 | 42 | ```sh 43 | cargo test 44 | ``` 45 | 46 | ### Updating snapshots 47 | 48 | Install `insta` if necessary, and run the command: 49 | 50 | ```bash 51 | cargo install cargo-insta 52 | cargo insta review 53 | ``` 54 | 55 | ## IDE integration 56 | 57 | ### Using VSCode to work on memfaultd 58 | 59 | VSCode rust plugin will not find the `Cargo.toml` file unless you open the 60 | `meta-memfault/recipes-memfault/memfaultd/files/memfaultd/` directly. 61 | -------------------------------------------------------------------------------- /memfaultd/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 - Present, Memfault 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code or in binary form must reproduce 8 | the above copyright notice, this list of conditions and the following 9 | disclaimer in the documentation and/or other materials provided with the 10 | distribution. 11 | 12 | 2. Neither the name of Memfault nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | 3. This software, with or without modification, must only be used with 17 | the Memfault services and integrated with the Memfault server. 18 | 19 | 4. Any software provided in binary form under this license must not be 20 | reverse engineered, decompiled, modified and/or disassembled. 21 | 22 | THIS SOFTWARE IS PROVIDED BY MEMFAULT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 24 | NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | SHALL MEMFAULT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /memfaultd/README.md: -------------------------------------------------------------------------------- 1 | # `memfaultd` 2 | 3 | `memfaultd` is a daemon that runs on your device and collects crash reports and 4 | metrics. It is the core of the 5 | [Memfault Linux SDK](https://github.com/memfault/memfault-linux-sdk/blob/kirkstone/README.md). 6 | 7 | ## Overview 8 | 9 | `memfaultd` supports several features to help you maintain and debug your fleet 10 | of devices: 11 | 12 | - **Crash reporting**: When your device crashes, `memfaultd` collects a crash 13 | report from 14 | [Linux Coredumps](https://man7.org/linux/man-pages/man5/core.5.html). For more 15 | information, see the 16 | [Coredumps documentation](https://docs.memfault.com/docs/linux/coredumps). 17 | 18 | - **Metrics**: `memfaultd` collects metrics from your device and uploads them to 19 | Memfault. For more information, see the 20 | [Metrics documentation](https://docs.memfault.com/docs/linux/metrics). 21 | 22 | - **Reboot reason tracking**: `memfaultd` detects various reboot reasons from 23 | the system and reports them to the Memfault Dashboard. Users can also provide 24 | a specific reboot reason before restarting the device. For more information, 25 | see the 26 | [Reboot Reason Tracking documentation](https://docs.memfault.com/docs/linux/reboot-reason-tracking). 27 | 28 | - **OTA Updates**: `memfaultd` supports [SWUpdate](https://swupdate.org/) out of 29 | the box and is able to configure it to talk to our hawkBit DDI-compatible 30 | endpoint. For more information, see the 31 | [Linux OTA Management documentation](https://docs.memfault.com/docs/linux/ota). 32 | 33 | - **Logging**: `memfaultd` collects logs from your system. For more information, 34 | see the [Logging documentation](https://docs.memfault.com/docs/linux/logging). 35 | 36 | And much more! [Register](https://app.memfault.com/register) and get started 37 | today! 38 | -------------------------------------------------------------------------------- /memfaultd/VERSION: -------------------------------------------------------------------------------- 1 | BUILD ID: 3112275 2 | GIT COMMIT: eaa113a284 3 | VERSION: 1.21.1 4 | -------------------------------------------------------------------------------- /memfaultd/memfaultd.conf: -------------------------------------------------------------------------------- 1 | /* 2 | See builtin.conf (in the source files) for configuration options. 3 | At minimum, your override of this file should provide these keys: 4 | { 5 | "software_version": "", 6 | "software_type": "", 7 | "project_key": "", 8 | "persist_dir": "" 9 | } 10 | */ 11 | 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/bin/memfault-core-handler.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use memfaultd::cli; 5 | 6 | /// memfault-core-handlers is an alias to the main function in cli.rs 7 | /// 8 | /// For further details, see comments on memfaultd.rs 9 | fn main() { 10 | cli::main() 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/bin/memfaultctl.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use memfaultd::cli; 5 | 6 | /// memfaultctl is an alias to the main function in cli.rs 7 | /// 8 | /// For further details, see comments on memfaultd.rs 9 | fn main() { 10 | cli::main() 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/bin/memfaultd.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use memfaultd::cli; 5 | 6 | /// memfaultd is an alias to the main function in cli.rs 7 | /// 8 | /// In the target machine, memfaultd is the only binary that remains. memfaultctl and 9 | /// memfault-core-handler are symlinked by build scripts. In the case of Yocto, this is 10 | /// meta-memfault/recipes-memfault/memfaultd/memfaultd.bb 11 | /// 12 | /// The binary setup in this crate could opt for a single bin/memfaultd.rs entrypoint, however 13 | /// setting up three different binaries makes development easier because it mimics what build 14 | /// systems do in target devices. 15 | /// 16 | /// Alternative solutions are possible, for example adding a post-build script that does the 17 | /// symlinking manually in the build directory. 18 | fn main() { 19 | cli::main() 20 | } 21 | -------------------------------------------------------------------------------- /memfaultd/src/bin/mfw.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use memfaultd::cli; 5 | 6 | /// mfw is an alias to the main function in cli.rs 7 | /// 8 | /// For further details, see comments on memfaultd.rs 9 | fn main() { 10 | cli::main() 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/cli/cargs.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use libc::c_char; 5 | use libc::c_int; 6 | use std::ffi::CString; 7 | use std::path::Path; 8 | 9 | pub struct CArgs { 10 | argv: Vec, 11 | argv_ptr: Vec<*const libc::c_char>, 12 | } 13 | 14 | impl CArgs { 15 | pub fn new(args: impl IntoIterator) -> Self { 16 | let argv: Vec<_> = args 17 | .into_iter() 18 | .map(|arg| CString::new(arg.as_str()).unwrap()) 19 | .collect(); 20 | let argv_ptr: Vec<_> = argv 21 | .iter() 22 | .map(|arg| arg.as_ptr()) 23 | .chain(std::iter::once(std::ptr::null())) 24 | .collect(); 25 | Self { argv, argv_ptr } 26 | } 27 | 28 | /// Returns the number of arguments, ie the C language's `argc`. 29 | pub fn argc(&self) -> c_int { 30 | self.argv.len() as c_int 31 | } 32 | 33 | /// Returns the C language's `argv` (`*const *const c_char`). 34 | pub fn argv(&self) -> *const *const c_char { 35 | self.argv_ptr.as_ptr() 36 | } 37 | 38 | /// Returns the name of the command invoked by the user - removing any path information. 39 | pub fn name(&self) -> &str { 40 | Path::new(self.argv[0].to_str().unwrap()) 41 | .file_name() 42 | .unwrap() 43 | .to_str() 44 | .unwrap() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/elf-core-runtime-ld-paths.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memfault/memfaultd/1a4450d5dbd27a7a019e100f18eba5b22656abe6/memfaultd/src/cli/memfault_core_handler/fixtures/elf-core-runtime-ld-paths.elf -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/sample_note.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memfault/memfaultd/1a4450d5dbd27a7a019e100f18eba5b22656abe6/memfaultd/src/cli/memfault_core_handler/fixtures/sample_note.bin -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/README.md: -------------------------------------------------------------------------------- 1 | # Simple Executable for stack unwinding tests 2 | 3 | This is a simple executable that can be used to test stack unwinding. The main 4 | goal is to have a simple crashing c program that has multiple stack frames, and 5 | is easily reproducible. Note that this is expected to be built on an x86_64 6 | Linux machine. If it is built on a different architecture, the stack unwinding 7 | may not work as expected for the tests 8 | 9 | ## Build Instructions 10 | 11 | To build the executable, run the following command: 12 | 13 | ```bash 14 | gcc -s -fasynchronous-unwind-tables -xc simple_exe.c -o simple_exe.elf 15 | ``` 16 | 17 | The included binary was created for and on an x86_64 Linux machine. 18 | 19 | ## Creating a Coredump 20 | 21 | To create the included coredump set your core pattern with the following 22 | command: 23 | 24 | ```bash 25 | echo "/tmp/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern 26 | ``` 27 | 28 | Then run the executable, and the coredump will be present in `/tmp`. 29 | 30 | ## Getting `libc` `.eh_frame` data 31 | 32 | The test for stack unwinding requires the `.eh_frame` data for the `libc` that 33 | was used to build the executable. Rather than include all of libc which could be 34 | quite large you can strip everything out with the following command: 35 | 36 | ```bash 37 | objcopy --only-section=.eh_frame --only-section=.eh_frame_hdr /usr/lib/x86_64-linux-gnu/libc.so.6 libc_ehframe.elf 38 | ``` 39 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/libc_ehframe.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memfault/memfaultd/1a4450d5dbd27a7a019e100f18eba5b22656abe6/memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/libc_ehframe.elf -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/simple_exe.c: -------------------------------------------------------------------------------- 1 | //! @file 2 | //! 3 | //! Copyright (c) Memfault, Inc. 4 | //! See License.txt for details 5 | //! 6 | //! @brief 7 | //! 8 | 9 | #include 10 | #include 11 | 12 | void function_c(char *str) { 13 | char *crash = NULL; 14 | *crash = 'a'; 15 | } 16 | 17 | void function_b(char *str) { 18 | printf("Function B: Calling function C\n"); 19 | function_c(str); 20 | } 21 | 22 | void function_a(char *str) { 23 | printf("Function A: Calling function B\n"); 24 | function_b(str); 25 | } 26 | 27 | int main() { 28 | // A simple string to pass to the function 29 | char *long_string = "a"; 30 | printf("Main: Starting program\n"); 31 | function_a(long_string); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/simple_exe.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memfault/memfaultd/1a4450d5dbd27a7a019e100f18eba5b22656abe6/memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/simple_exe.elf -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/simple_exe_core.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memfault/memfaultd/1a4450d5dbd27a7a019e100f18eba5b22656abe6/memfaultd/src/cli/memfault_core_handler/fixtures/simple_executable/simple_exe_core.elf -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/snapshots/memfaultd__cli__memfault_core_handler__core_elf_memfault_note__test__serialize_debug_data.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/memfault_core_handler/core_elf_memfault_note.rs 3 | expression: deser_capture_logs 4 | --- 5 | Map( 6 | [ 7 | ( 8 | Text( 9 | "schema_version", 10 | ), 11 | Integer( 12 | Integer( 13 | 1, 14 | ), 15 | ), 16 | ), 17 | ( 18 | Text( 19 | "capture_logs", 20 | ), 21 | Array( 22 | [ 23 | Text( 24 | "Error 1", 25 | ), 26 | Text( 27 | "Error 2", 28 | ), 29 | Text( 30 | "Error 3", 31 | ), 32 | ], 33 | ), 34 | ), 35 | ], 36 | ) 37 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/snapshots/memfaultd__cli__memfault_core_handler__elf_utils__test__get_build_id.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/memfault_core_handler/elf_utils.rs 3 | expression: build_id 4 | --- 5 | [ 6 | 79, 7 | 9, 8 | 180, 9 | 226, 10 | 186, 11 | 202, 12 | 75, 13 | 209, 14 | 31, 15 | 154, 16 | 186, 17 | 199, 18 | 234, 19 | 48, 20 | 220, 21 | 89, 22 | 64, 23 | 85, 24 | 85, 25 | 84, 26 | ] 27 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/snapshots/memfaultd__cli__memfault_core_handler__elf_utils__test__section_name_read.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/memfault_core_handler/elf_utils.rs 3 | expression: names 4 | --- 5 | [ 6 | "", 7 | ".bss", 8 | ".comment", 9 | ".data", 10 | ".dynamic", 11 | ".dynstr", 12 | ".dynsym", 13 | ".eh_frame", 14 | ".eh_frame_hdr", 15 | ".fini", 16 | ".fini_array", 17 | ".gnu.hash", 18 | ".gnu.version", 19 | ".gnu.version_r", 20 | ".got", 21 | ".init", 22 | ".init_array", 23 | ".interp", 24 | ".note.ABI-tag", 25 | ".note.gnu.build-id", 26 | ".note.gnu.property", 27 | ".plt", 28 | ".plt.got", 29 | ".plt.sec", 30 | ".rela.dyn", 31 | ".rela.plt", 32 | ".rodata", 33 | ".shstrtab", 34 | ".text", 35 | ] 36 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/snapshots/memfaultd__cli__memfault_core_handler__find_dynamic__test__find_dynamic_linker_ranges.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/memfault_core_handler/find_dynamic.rs 3 | expression: output 4 | --- 5 | [ 6 | MemoryRange { 7 | start: "0x5587ae8bd040", 8 | end: "0x5587ae8bd318", 9 | }, 10 | MemoryRange { 11 | start: "0x5587ae8c0dc0", 12 | end: "0x5587ae8c0fc0", 13 | }, 14 | MemoryRange { 15 | start: "0x7f6e38fad118", 16 | end: "0x7f6e38fad140", 17 | }, 18 | MemoryRange { 19 | start: "0x7f6e38fad2e0", 20 | end: "0x7f6e38fad308", 21 | }, 22 | MemoryRange { 23 | start: "0x7f6e38fad8b0", 24 | end: "0x7f6e38fad8d8", 25 | }, 26 | MemoryRange { 27 | start: "0x7f6e38f781e0", 28 | end: "0x7f6e38f78208", 29 | }, 30 | MemoryRange { 31 | start: "0x7f6e38f78760", 32 | end: "0x7f6e38f78788", 33 | }, 34 | MemoryRange { 35 | start: "0x7f6e38facad0", 36 | end: "0x7f6e38facaf8", 37 | }, 38 | MemoryRange { 39 | start: "0x7f6e38fad8a0", 40 | end: "0x7f6e38fad8a1", 41 | }, 42 | MemoryRange { 43 | start: "0x7ffe4bb1f371", 44 | end: "0x7ffe4bb1f381", 45 | }, 46 | MemoryRange { 47 | start: "0x7f6e38f781d0", 48 | end: "0x7f6e38f781dc", 49 | }, 50 | MemoryRange { 51 | start: "0x7f6e38f78740", 52 | end: "0x7f6e38f78760", 53 | }, 54 | MemoryRange { 55 | start: "0x5587ae8bd318", 56 | end: "0x5587ae8bd334", 57 | }, 58 | ] 59 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/snapshots/memfaultd__cli__memfault_core_handler__log_wrapper__test__log_saving.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/memfault_core_handler/log_wrapper.rs 3 | expression: errors 4 | --- 5 | [ 6 | "ERROR test:71 - Test message", 7 | "WARN test:71 - Test message", 8 | "INFO test:71 - Test message", 9 | "DEBUG test:71 - Test message" 10 | ] 11 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/stack_unwinder/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod eh_frame_finder; 5 | mod stacktrace_format; 6 | mod unwind_handler; 7 | mod unwinder; 8 | 9 | pub use eh_frame_finder::EhFrameFinderImpl; 10 | pub use unwind_handler::UnwindHandler; 11 | pub use unwinder::{UnwindFrameContext, Unwinder}; 12 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfault_core_handler/stack_unwinder/snapshots/memfaultd__cli__memfault_core_handler__stack_unwinder__unwind_handler__test__unwind_stack.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/memfault_core_handler/stack_unwinder/unwind_handler.rs 3 | expression: stacktrace 4 | snapshot_kind: text 5 | --- 6 | { 7 | "version": "1", 8 | "signal": "SIGSEGV", 9 | "cmdline": "simple_exe", 10 | "symbols": [ 11 | { 12 | "pc_range": { 13 | "start": "0x75959a428000", 14 | "end": "0x75959a5bd000" 15 | }, 16 | "build_id": "abcd1234", 17 | "compiled_offset": "0x28000", 18 | "runtime_offset": "0x75959a428000", 19 | "path": "test_path" 20 | }, 21 | { 22 | "pc_range": { 23 | "start": "0x63010b1cf000", 24 | "end": "0x63010b1d0000" 25 | }, 26 | "build_id": "abcd1234", 27 | "compiled_offset": "0x1000", 28 | "runtime_offset": "0x63010b1cf000", 29 | "path": "test_path" 30 | } 31 | ], 32 | "threads": [ 33 | { 34 | "active": true, 35 | "pcs": [ 36 | "0x63010b1cf161", 37 | "0x63010b1cf191", 38 | "0x63010b1cf1bf", 39 | "0x63010b1cf1f4", 40 | "0x75959a429d8f", 41 | "0x75959a429e3f", 42 | "0x63010b1cf084" 43 | ] 44 | } 45 | ], 46 | "core_handler_logs": [ 47 | "Ranger", 48 | "Daisy", 49 | "Carlton" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfaultctl/add_battery_reading.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::config::Config; 5 | use eyre::{eyre, Result}; 6 | 7 | use crate::cli::memfaultd_client::MemfaultdClient; 8 | 9 | pub fn add_battery_reading(config: &Config, reading_string: &str) -> Result<()> { 10 | let client = MemfaultdClient::from_config(config)?; 11 | 12 | match client.add_battery_reading(reading_string) { 13 | Ok(()) => { 14 | eprintln!("Successfully published battery reading to memfaultd"); 15 | Ok(()) 16 | } 17 | Err(e) => Err(eyre!("add-battery-reading failed: {:#}", e)), 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfaultctl/report_sync.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::config::Config; 5 | use eyre::{eyre, Result}; 6 | 7 | use crate::cli::memfaultd_client::MemfaultdClient; 8 | 9 | pub fn report_sync(config: &Config, success: bool) -> Result<()> { 10 | let client = MemfaultdClient::from_config(config)?; 11 | let status = if success { "successful" } else { "failed" }; 12 | let command_string = if success { 13 | "report-sync-success " 14 | } else { 15 | "report-sync-failure" 16 | }; 17 | 18 | match client.report_sync(success) { 19 | Ok(()) => { 20 | eprintln!("Reported a {} sync to memfaultd", status); 21 | Ok(()) 22 | } 23 | Err(e) => Err(eyre!("{} failed: {:#}", command_string, e)), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfaultctl/session.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use eyre::{eyre, Result}; 5 | 6 | use crate::config::Config; 7 | use crate::{ 8 | cli::memfaultd_client::MemfaultdClient, 9 | metrics::{KeyedMetricReading, SessionName}, 10 | }; 11 | 12 | pub fn start_session( 13 | config: &Config, 14 | session_name: SessionName, 15 | metric_readings: Vec, 16 | ) -> Result<()> { 17 | let client = MemfaultdClient::from_config(config)?; 18 | if config.config_file.enable_data_collection { 19 | match client.start_session(session_name.clone(), metric_readings) { 20 | Ok(()) => { 21 | eprintln!("Started new {} session", session_name); 22 | Ok(()) 23 | } 24 | Err(e) => Err(eyre!("start-session failed: {:?}", e)), 25 | } 26 | } else { 27 | Err(eyre!( 28 | "Cannot start session with data collection disabled.\n\ 29 | You can enable data collection with \"memfaultctl enable-data-collection\"" 30 | )) 31 | } 32 | } 33 | 34 | pub fn end_session( 35 | config: &Config, 36 | session_name: SessionName, 37 | readings: Vec, 38 | ) -> Result<()> { 39 | let client = MemfaultdClient::from_config(config)?; 40 | if config.config_file.enable_data_collection { 41 | match client.end_session(session_name.clone(), readings) { 42 | Ok(()) => { 43 | eprintln!("Ended ongoing {} session", session_name); 44 | Ok(()) 45 | } 46 | Err(e) => Err(eyre!("end-session failed: {:?}", e)), 47 | } 48 | } else { 49 | Err(eyre!( 50 | "Cannot end session with data collection disabled.\n\ 51 | You can enable data collection with \"memfaultctl enable-data-collection\"" 52 | )) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfaultctl/sync.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use eyre::{eyre, Result}; 5 | 6 | use crate::util::ipc::send_flush_signal; 7 | 8 | pub fn sync(skip_serialization: bool) -> Result<()> { 9 | match send_flush_signal(skip_serialization) { 10 | Ok(()) => Ok(()), 11 | Err(e) => Err(eyre!( 12 | "Error: {} If you are not running memfaultd as a daemon you \ 13 | can force it to sync data with \ 14 | 'killall -USR1 memfaultd'.", 15 | e 16 | )), 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /memfaultd/src/cli/memfaultctl/write_metrics.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::{cli::MemfaultdClient, config::Config, metrics::KeyedMetricReading}; 5 | 6 | use eyre::Result; 7 | 8 | pub fn write_metrics(metrics: Vec, config: &Config) -> Result<()> { 9 | let client = MemfaultdClient::from_config(config)?; 10 | client.post_metrics(metrics) 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/cli/snapshots/memfaultd__cli__show_settings__tests__test.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/cli/show_settings.rs 3 | expression: output 4 | --- 5 | Base configuration (/etc/memfaultd.conf): 6 | { 7 | "project_key": "xyz" 8 | } 9 | 10 | Runtime configuration: 11 | { 12 | "enable_data_collection": true 13 | } 14 | 15 | Device configuration from memfault-device-info: 16 | MEMFAULT_DEVICE_ID=X 17 | MEMFAULT_HARDWARE_VERSION=Y 18 | 19 | Memfault version: 20 | VERSION=1.2.3 21 | GIT COMMIT=abcdef 22 | BUILD ID=123456 23 | 24 | Features enabled: 25 | reboot 26 | coredump 27 | -------------------------------------------------------------------------------- /memfaultd/src/cli/version.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::build_info::{BUILD_ID, GIT_COMMIT, VERSION}; 5 | 6 | pub fn format_version() -> String { 7 | format!( 8 | "VERSION={}\nGIT COMMIT={}\nBUILD ID={}", 9 | VERSION, GIT_COMMIT, BUILD_ID 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/fixtures/statsd-counter-first-seen.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "values": [null], 4 | "dstypes": ["derive"], 5 | "dsnames": ["value"], 6 | "time": 1698360252.757, 7 | "interval": 10.0, 8 | "host": "linux-devbox", 9 | "plugin": "statsd", 10 | "plugin_instance": "", 11 | "type": "derive", 12 | "type_instance": "mypythonapp.counter1" 13 | }, 14 | { 15 | "values": [2], 16 | "dstypes": ["gauge"], 17 | "dsnames": ["value"], 18 | "time": 1698360252.757, 19 | "interval": 10.0, 20 | "host": "linux-devbox", 21 | "plugin": "statsd", 22 | "plugin_instance": "", 23 | "type": "count", 24 | "type_instance": "mypythonapp.counter1" 25 | }, 26 | { 27 | "values": [null], 28 | "dstypes": ["derive"], 29 | "dsnames": ["value"], 30 | "time": 1698360252.757, 31 | "interval": 10.0, 32 | "host": "linux-devbox", 33 | "plugin": "statsd", 34 | "plugin_instance": "", 35 | "type": "derive", 36 | "type_instance": "mypythonapp.counter2" 37 | }, 38 | { 39 | "values": [20], 40 | "dstypes": ["gauge"], 41 | "dsnames": ["value"], 42 | "time": 1698360252.757, 43 | "interval": 10.0, 44 | "host": "linux-devbox", 45 | "plugin": "statsd", 46 | "plugin_instance": "", 47 | "type": "count", 48 | "type_instance": "mypythonapp.counter2" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/fixtures/statsd-counter.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "values": [1], 4 | "dstypes": ["gauge"], 5 | "dsnames": ["value"], 6 | "time": 1698360892.757, 7 | "interval": 10.0, 8 | "host": "linux-devbox", 9 | "plugin": "statsd", 10 | "plugin_instance": "", 11 | "type": "count", 12 | "type_instance": "mypythonapp.counter1" 13 | }, 14 | { 15 | "values": [0.999995505178062], 16 | "dstypes": ["derive"], 17 | "dsnames": ["value"], 18 | "time": 1698360892.757, 19 | "interval": 10.0, 20 | "host": "linux-devbox", 21 | "plugin": "statsd", 22 | "plugin_instance": "", 23 | "type": "derive", 24 | "type_instance": "mypythonapp.counter2" 25 | }, 26 | { 27 | "values": [10], 28 | "dstypes": ["gauge"], 29 | "dsnames": ["value"], 30 | "time": 1698360892.757, 31 | "interval": 10.0, 32 | "host": "linux-devbox", 33 | "plugin": "statsd", 34 | "plugin_instance": "", 35 | "type": "count", 36 | "type_instance": "mypythonapp.counter2" 37 | }, 38 | { 39 | "values": [0.0999993716964859], 40 | "dstypes": ["derive"], 41 | "dsnames": ["value"], 42 | "time": 1698360892.757, 43 | "interval": 10.0, 44 | "host": "linux-devbox", 45 | "plugin": "statsd", 46 | "plugin_instance": "", 47 | "type": "derive", 48 | "type_instance": "mypythonapp.counter1" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod payload; 5 | 6 | mod collectd_handler; 7 | pub use collectd_handler::CollectdHandler; 8 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/snapshots/memfaultd__collectd__collectd_handler__tests__drops_cpu_metrics_when_builtin_system_metrics_are_enabled.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/collectd/collectd_handler.rs 3 | expression: mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "cpufreq/0/cpu/idle": 0.0, 7 | "mockplugin/0/mock/test": 0.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/snapshots/memfaultd__collectd__collectd_handler__tests__handle_push.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/collectd/collectd_handler.rs 3 | expression: fixture.mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "cpu/0/cpu/idle": 0.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/snapshots/memfaultd__collectd__payload__tests__sample-with-null.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/collectd/payload.rs 3 | expression: metadatas 4 | --- 5 | [ 6 | { 7 | "name": "uptime/uptime", 8 | "value": { 9 | "Histogram": { 10 | "value": 973577.0, 11 | "timestamp": "2023-06-06T22:04:02.785Z" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "memory/memory/inactive", 17 | "value": { 18 | "Histogram": { 19 | "value": 11160961024.0, 20 | "timestamp": "2023-06-06T22:04:02.785Z" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "memory/memory/active", 26 | "value": { 27 | "Histogram": { 28 | "value": 11797676032.0, 29 | "timestamp": "2023-06-06T22:04:02.785Z" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "memory/memory/wired", 35 | "value": { 36 | "Histogram": { 37 | "value": 3427991552.0, 38 | "timestamp": "2023-06-06T22:04:02.785Z" 39 | } 40 | } 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/snapshots/memfaultd__collectd__payload__tests__statsd-counter-first-seen.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/collectd/payload.rs 3 | expression: metadatas 4 | --- 5 | [ 6 | { 7 | "name": "statsd/count/mypythonapp.counter1", 8 | "value": { 9 | "Counter": { 10 | "value": 2.0, 11 | "timestamp": "2023-10-26T22:44:12.757Z" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "statsd/count/mypythonapp.counter2", 17 | "value": { 18 | "Counter": { 19 | "value": 20.0, 20 | "timestamp": "2023-10-26T22:44:12.757Z" 21 | } 22 | } 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /memfaultd/src/collectd/snapshots/memfaultd__collectd__payload__tests__statsd-counter.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/collectd/payload.rs 3 | expression: metadatas 4 | --- 5 | [ 6 | { 7 | "name": "statsd/count/mypythonapp.counter1", 8 | "value": { 9 | "Counter": { 10 | "value": 1.0, 11 | "timestamp": "2023-10-26T22:54:52.757Z" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "statsd/derive/mypythonapp.counter2", 17 | "value": { 18 | "Histogram": { 19 | "value": 0.999995505178062, 20 | "timestamp": "2023-10-26T22:54:52.757Z" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "statsd/count/mypythonapp.counter2", 26 | "value": { 27 | "Counter": { 28 | "value": 10.0, 29 | "timestamp": "2023-10-26T22:54:52.757Z" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "statsd/derive/mypythonapp.counter1", 35 | "value": { 36 | "Histogram": { 37 | "value": 0.0999993716964859, 38 | "timestamp": "2023-10-26T22:54:52.757Z" 39 | } 40 | } 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /memfaultd/src/config/snapshots/memfaultd__config__config_file__test__set_and_write_bool_to_runtime_config@empty_object.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/config/config_file.rs 3 | expression: disk_config_string 4 | --- 5 | "{\"key\":true}" 6 | -------------------------------------------------------------------------------- /memfaultd/src/config/snapshots/memfaultd__config__config_file__test__set_and_write_bool_to_runtime_config@no_file.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/config/config_file.rs 3 | expression: disk_config_string 4 | --- 5 | "{\"key\":true}" 6 | -------------------------------------------------------------------------------- /memfaultd/src/config/snapshots/memfaultd__config__config_file__test__set_and_write_bool_to_runtime_config@other_key.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/config/config_file.rs 3 | expression: disk_config_string 4 | --- 5 | "{\"key\":true,\"key2\":false}" 6 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/empty_object.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/log_filters.json: -------------------------------------------------------------------------------- 1 | { 2 | "logs": { 3 | "filtering": { 4 | "default_action": "exclude", 5 | "rules": [ 6 | { 7 | "service": "init.scope", 8 | "pattern": "(.*): Scheduled restart job, restart counter is at", 9 | "counter_name": "systemd_unit_restart_$1", 10 | "action": "include" 11 | }, 12 | { 13 | "extra_fields": { "pod_identifier": "init.scope" }, 14 | "pattern": "(.*): Scheduled restart job, restart counter is at", 15 | "counter_name": "systemd_unit_restart_$1", 16 | "action": "include" 17 | }, 18 | { 19 | "message": "Out of memory: Killed process \\d+ \\((.*)\\)", 20 | "counter_name": "oom_killed_$1", 21 | "action": "include" 22 | }, 23 | { 24 | "message": "Connected to * port 443", 25 | "service": "camera_monitor", 26 | "level": "DEBUG", 27 | "action": "exclude" 28 | }, 29 | { 30 | "service": "NetworkManager", 31 | "level": "TRACE", 32 | "action": "exclude" 33 | }, 34 | { 35 | "service": "NetworkManager", 36 | "level": "DEBUG", 37 | "action": "exclude" 38 | } 39 | ] 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/metrics_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "metrics": { 3 | "enable_daily_heartbeats": false, 4 | "system_metric_collection": { 5 | "enable": false, 6 | "poll_interval_seconds": 10, 7 | "processes": ["wefaultd"], 8 | "disk_space": ["/dev/sda1"], 9 | "network_interfaces": ["eth1"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/syslog.json: -------------------------------------------------------------------------------- 1 | { 2 | "logs": { 3 | "source": { 4 | "syslog": { 5 | "bind_address": "127.0.0.1:514" 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_connectivity_monitor.json: -------------------------------------------------------------------------------- 1 | { 2 | "connectivity_monitor": { 3 | "interval_seconds": 30, 4 | "timeout_seconds": 10, 5 | "targets": [ 6 | { 7 | "host": "8.8.8.8", 8 | "port": 443, 9 | "protocol": "tcp" 10 | } 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_coredump_capture_strategy_threads.json: -------------------------------------------------------------------------------- 1 | { 2 | "coredump": { 3 | "capture_strategy": { 4 | "type": "threads", 5 | "max_thread_size_kib": 32 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_invalid_path.json: -------------------------------------------------------------------------------- 1 | { 2 | "tmp_dir": "tmp" 3 | } 4 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_invalid_swt_swv.json: -------------------------------------------------------------------------------- 1 | { 2 | "software_version": "1.0.0?", 3 | "software_type": "test program" 4 | } 5 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_log_to_metrics_rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "logs": { 3 | "log_to_metrics": { 4 | "rules": [ 5 | { 6 | "type": "count_matching", 7 | "pattern": "ssh", 8 | "metric_name": "ssh_logins" 9 | }, 10 | { 11 | "type": "count_matching", 12 | "pattern": "ssh", 13 | "metric_name": "ssh_logins", 14 | "filter": { 15 | "_SYSTEMD_UNIT": "sshd.service" 16 | } 17 | } 18 | ] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_partial_logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "logs": { 3 | "bind_address": "0.0.0.0:4242" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_sessions.json: -------------------------------------------------------------------------------- 1 | { 2 | "sessions": [ 3 | { 4 | "name": "test-session", 5 | "captured_metrics": ["cpu.total"] 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_sessions_invalid_metric_name.json: -------------------------------------------------------------------------------- 1 | { 2 | "sessions": [ 3 | { 4 | "name": "test-session", 5 | "captured_metrics": [ 6 | "string-with-non-ascii-\u{1F4A9}", 7 | "statsd.wefaultd.blendpower" 8 | ] 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/with_sessions_invalid_session_name.json: -------------------------------------------------------------------------------- 1 | { 2 | "sessions": [ 3 | { 4 | "name": "123-test-session", 5 | "captured_metrics": ["cpu.total", "statsd.wefaultd.blendpower"] 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/config/test-config/without_coredump_compression.json: -------------------------------------------------------------------------------- 1 | { 2 | "coredump": { 3 | "compression": "none" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /memfaultd/src/config/utils.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::util::patterns::{ 5 | alphanum_slug_dots_colon_is_valid, alphanum_slug_dots_colon_spaces_parens_slash_is_valid, 6 | alphanum_slug_is_valid, 7 | }; 8 | 9 | pub fn software_type_is_valid(s: &str) -> eyre::Result<()> { 10 | alphanum_slug_dots_colon_is_valid(s, 128) 11 | } 12 | 13 | pub fn software_version_is_valid(s: &str) -> eyre::Result<()> { 14 | alphanum_slug_dots_colon_spaces_parens_slash_is_valid(s, 128) 15 | } 16 | 17 | pub fn hardware_version_is_valid(s: &str) -> eyre::Result<()> { 18 | alphanum_slug_dots_colon_is_valid(s, 128) 19 | } 20 | 21 | pub fn device_id_is_valid(id: &str) -> eyre::Result<()> { 22 | alphanum_slug_is_valid(id, 128) 23 | } 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | use rstest::rstest; 29 | 30 | #[rstest] 31 | // Minimum 1 character 32 | #[case("A", true)] 33 | // Allowed characters 34 | #[case( 35 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_-", 36 | true 37 | )] 38 | // Disallowed characters 39 | #[case("DEMO.1234", false)] 40 | #[case("DEMO 1234", false)] 41 | // Too short (0 characters) 42 | #[case("", false)] 43 | // Too long (129 characters) 44 | #[case("012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345679012345678901234567890", false)] 45 | fn device_id_is_valid_works(#[case] device_id: &str, #[case] expected: bool) { 46 | assert_eq!(device_id_is_valid(device_id).is_ok(), expected); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /memfaultd/src/coredump/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use eyre::Result; 5 | use std::path::Path; 6 | 7 | #[cfg_attr(not(target_os = "linux"), allow(unused_variables))] 8 | pub fn coredump_configure_kernel(config_path: &Path) -> Result<()> { 9 | #[cfg(target_os = "linux")] 10 | { 11 | use eyre::Context; 12 | use std::fs::write; 13 | 14 | write( 15 | "/proc/sys/kernel/core_pattern", 16 | format!( 17 | "|/usr/sbin/memfault-core-handler -c {} %P %I %s", 18 | config_path.display() 19 | ), 20 | ) 21 | .wrap_err("Unable to write coredump pattern") 22 | } 23 | #[cfg(not(target_os = "linux"))] 24 | { 25 | use log::warn; 26 | 27 | warn!("Skipping coredump setting on non-Linux systems."); 28 | Ok(()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /memfaultd/src/http_server/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | //! Memfaultd HTTP server 5 | //! Used on device for communication with other programs and `memfaultctl`. 6 | //! 7 | //! Typically binds to 127.0.0.1 and only available locally. 8 | //! 9 | mod handler; 10 | mod request_bodies; 11 | mod server; 12 | mod utils; 13 | 14 | pub use handler::{HttpHandler, HttpHandlerResult}; 15 | pub use server::HttpServer; 16 | 17 | pub use utils::{parse_query_params, ConvenientHeader}; 18 | 19 | pub use request_bodies::{MetricsRequest, SessionRequest}; 20 | -------------------------------------------------------------------------------- /memfaultd/src/http_server/request_bodies.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use serde::{Deserialize, Serialize}; 5 | 6 | use crate::metrics::{KeyedMetricReading, SessionName}; 7 | 8 | #[derive(Serialize, Deserialize)] 9 | pub struct SessionRequest { 10 | pub session_name: SessionName, 11 | pub readings: Vec, 12 | } 13 | 14 | impl SessionRequest { 15 | pub fn new(session_name: SessionName, readings: Vec) -> Self { 16 | Self { 17 | session_name, 18 | readings, 19 | } 20 | } 21 | 22 | pub fn new_without_readings(session_name: SessionName) -> Self { 23 | Self { 24 | session_name, 25 | readings: vec![], 26 | } 27 | } 28 | } 29 | 30 | #[derive(Serialize, Deserialize)] 31 | pub struct MetricsRequest { 32 | pub readings: Vec, 33 | } 34 | 35 | impl MetricsRequest { 36 | pub fn new(readings: Vec) -> Self { 37 | Self { readings } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /memfaultd/src/http_server/utils.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::collections::HashMap; 5 | 6 | use eyre::{eyre, Result}; 7 | use tiny_http::Header; 8 | 9 | /// Wraps Header.from_bytes into something that returns a Result<> compatible with eyre::Result. 10 | pub trait ConvenientHeader { 11 | fn from_strings(name: &str, value: &str) -> Result
; 12 | } 13 | impl ConvenientHeader for Header { 14 | fn from_strings(name: &str, value: &str) -> Result
{ 15 | Header::from_bytes(name, value).map_err(|_e| eyre!("Invalid header ({}: {})", name, value)) 16 | } 17 | } 18 | 19 | /// Parses query parameters from a URL string 20 | /// NOTE: Support for decoding URL encoded parameters is not currently implemented 21 | pub fn parse_query_params(url_string: &str) -> HashMap { 22 | let mut params = HashMap::new(); 23 | 24 | let query_string = url_string.split('?').nth(1).unwrap_or(""); 25 | 26 | for param in query_string.split('&') { 27 | if param.is_empty() { 28 | continue; 29 | } 30 | 31 | let mut parts = param.split('='); 32 | let key = parts.next().unwrap_or(""); 33 | let value = parts.next().unwrap_or(""); 34 | 35 | params.insert(key.to_string(), value.to_string()); 36 | } 37 | 38 | params 39 | } 40 | -------------------------------------------------------------------------------- /memfaultd/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(clippy::print_stdout, clippy::print_stderr)] 2 | // 3 | // Copyright (c) Memfault, Inc. 4 | // See License.txt for details 5 | 6 | pub mod cli; 7 | mod collectd; 8 | pub mod config; 9 | #[cfg(feature = "coredump")] 10 | mod coredump; 11 | #[cfg(feature = "logging")] 12 | mod fluent_bit; 13 | 14 | pub mod http_server; 15 | #[cfg(feature = "logging")] 16 | pub mod logs; 17 | pub mod mar; 18 | mod memfaultd; 19 | pub mod metrics; 20 | mod mmc; 21 | mod network; 22 | mod reboot; 23 | mod retriable_error; 24 | mod service_manager; 25 | #[cfg(feature = "swupdate")] 26 | mod swupdate; 27 | #[cfg(test)] 28 | mod test_utils; 29 | pub mod util; 30 | 31 | pub mod build_info { 32 | include!(concat!(env!("OUT_DIR"), "/build_info.rs")); 33 | } 34 | -------------------------------------------------------------------------------- /memfaultd/src/logs/completed_log.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use crate::mar::CompressionAlgorithm; 5 | use std::path::PathBuf; 6 | use uuid::Uuid; 7 | 8 | /// CompletedLog represents a log that has been rotated and is ready to be moved into the MAR 9 | /// staging area. 10 | pub struct CompletedLog { 11 | pub path: PathBuf, 12 | pub cid: Uuid, 13 | pub next_cid: Uuid, 14 | pub compression: CompressionAlgorithm, 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/logs/levels.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | pub const LOG_LEVEL_EMERGENCY: &str = "EMERGENCY"; 5 | pub const LOG_LEVEL_ALERT: &str = "ALERT"; 6 | pub const LOG_LEVEL_CRITICAL: &str = "CRITICAL"; 7 | pub const LOG_LEVEL_ERROR: &str = "ERROR"; 8 | pub const LOG_LEVEL_WARN: &str = "WARN"; 9 | pub const LOG_LEVEL_NOTICE: &str = "NOTICE"; 10 | pub const LOG_LEVEL_INFO: &str = "INFO"; 11 | pub const LOG_LEVEL_DEBUG: &str = "DEBUG"; 12 | 13 | // systemd severity codes 14 | pub const LOG_LEVEL_CODE_EMERGENCY: &str = "0"; 15 | pub const LOG_LEVEL_CODE_ALERT: &str = "1"; 16 | pub const LOG_LEVEL_CODE_CRITICAL: &str = "2"; 17 | pub const LOG_LEVEL_CODE_ERROR: &str = "3"; 18 | pub const LOG_LEVEL_CODE_WARN: &str = "4"; 19 | pub const LOG_LEVEL_CODE_NOTICE: &str = "5"; 20 | pub const LOG_LEVEL_CODE_INFO: &str = "6"; 21 | pub const LOG_LEVEL_CODE_DEBUG: &str = "7"; 22 | -------------------------------------------------------------------------------- /memfaultd/src/logs/messages.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use chrono::{DateTime, Utc}; 5 | use eyre::Result; 6 | use ssf::Message; 7 | 8 | use super::log_entry::LogEntry; 9 | 10 | pub struct FlushLogsMsg; 11 | 12 | impl Message for FlushLogsMsg { 13 | type Reply = Result<()>; 14 | } 15 | 16 | pub struct GetQueuedLogsMsg; 17 | 18 | impl Message for GetQueuedLogsMsg { 19 | type Reply = Result>; 20 | } 21 | pub struct GetLatestLogTimestampMsg; 22 | 23 | impl Message for GetLatestLogTimestampMsg { 24 | type Reply = Result>; 25 | } 26 | 27 | pub struct RotateIfNeededMsg; 28 | 29 | impl Message for RotateIfNeededMsg { 30 | type Reply = Result; 31 | } 32 | 33 | impl Message for LogEntry { 34 | type Reply = Result<()>; 35 | } 36 | 37 | pub struct RecoverLogsMsg; 38 | 39 | impl Message for RecoverLogsMsg { 40 | type Reply = Result; 41 | } 42 | 43 | pub struct LogEntryMsg { 44 | pub entry: LogEntry, 45 | pub dropped_msg_count: usize, 46 | } 47 | 48 | impl LogEntryMsg { 49 | pub fn new(entry: LogEntry, dropped_msg_count: usize) -> Self { 50 | Self { 51 | entry, 52 | dropped_msg_count, 53 | } 54 | } 55 | } 56 | 57 | impl Message for LogEntryMsg { 58 | type Reply = Result<()>; 59 | } 60 | -------------------------------------------------------------------------------- /memfaultd/src/logs/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | pub mod completed_log; 5 | pub mod messages; 6 | pub use completed_log::CompletedLog; 7 | pub mod log_collector; 8 | pub use log_collector::{LogCollector, LogCollectorConfig}; 9 | pub mod headroom; 10 | pub use headroom::HeadroomLimiter; 11 | #[cfg(feature = "systemd")] 12 | pub mod journald_parser; 13 | #[cfg(feature = "systemd")] 14 | pub mod journald_provider; 15 | pub mod levels; 16 | pub mod log_entry; 17 | mod log_file; 18 | pub mod log_filter; 19 | pub mod log_level_mapper; 20 | pub mod log_to_metrics; 21 | mod recovery; 22 | #[cfg(feature = "syslog")] 23 | pub mod syslog; 24 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__fluent_bit_adapter__tests__fluent_bit_adapter.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/fluent_bit_adapter.rs 3 | expression: log_entry 4 | --- 5 | { 6 | "ts": "2012-04-12T17:00:00+00:00", 7 | "data": { 8 | "MESSAGE": "test" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__journald_parser__test__from_raw_journal_entry.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/journald_parser.rs 3 | expression: entry 4 | --- 5 | { 6 | "ts": "1970-01-20T19:57:42.571Z", 7 | "fields": { 8 | "MESSAGE": "audit: type=1400 audit(1713462571.968:7508): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap.firefox.firefox\" name=\"/etc/fstab\" pid=10122 comm=\"firefox\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0", 9 | "_SYSTEMD_UNIT": "user@1000.service" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__journald_parser__test__journal_happy_path.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/journald_parser.rs 3 | expression: entry.unwrap() 4 | --- 5 | { 6 | "ts": "1970-01-20T19:57:42.571Z", 7 | "fields": { 8 | "MESSAGE": "audit: type=1400 audit(1713462571.968:7508): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap.firefox.firefox\" name=\"/etc/fstab\" pid=10122 comm=\"firefox\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0", 9 | "_SYSTEMD_UNIT": "user@1000.service" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__journald_provider__test__extra_attr.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/journald_provider.rs 3 | expression: entry 4 | snapshot_kind: text 5 | --- 6 | { 7 | "ts": "1970-01-01T00:00:01.337+00:00", 8 | "data": { 9 | "EXTRA_FIELD": "extra", 10 | "MESSAGE": "audit: type=1400 audit(1713462571.968:7508): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap.firefox.firefox\" name=\"/etc/fstab\" pid=10122 comm=\"firefox\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0", 11 | "_SYSTEMD_UNIT": "user@1000.service" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__journald_provider__test__no_extra_attr.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/journald_provider.rs 3 | expression: entry 4 | snapshot_kind: text 5 | --- 6 | { 7 | "ts": "1970-01-01T00:00:01.337+00:00", 8 | "data": { 9 | "MESSAGE": "audit: type=1400 audit(1713462571.968:7508): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap.firefox.firefox\" name=\"/etc/fstab\" pid=10122 comm=\"firefox\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0", 10 | "_SYSTEMD_UNIT": "user@1000.service" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_entry__tests__extra_attribute_filter.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_entry.rs 3 | expression: entry 4 | --- 5 | { 6 | "ts": "2012-04-12T17:00:00+00:00", 7 | "data": { 8 | "MESSAGE": "TEST", 9 | "SOME_EXTRA_KEY": "XX" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_entry__tests__extra_key.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_entry.rs 3 | expression: entry 4 | --- 5 | { 6 | "ts": "2012-04-12T17:00:00+00:00", 7 | "data": { 8 | "MESSAGE": "TEST" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_entry__tests__multi_key_match.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_entry.rs 3 | expression: entry 4 | --- 5 | { 6 | "ts": "2012-04-12T17:00:00+00:00", 7 | "data": { 8 | "MESSAGE": "TEST", 9 | "PRIORITY": "6", 10 | "_PID": "44", 11 | "_SYSTEMD_UNIT": "some.service" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_entry__tests__only_message.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_entry.rs 3 | expression: entry 4 | --- 5 | { 6 | "ts": "2012-04-12T17:00:00+00:00", 7 | "data": { 8 | "MESSAGE": "TEST" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__earlier_rules_take_priority-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | {} 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__earlier_rules_take_priority.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__filter_rules.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | {} 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_applied_before_filter_rules-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "polite_questions": 3.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_applied_before_filter_rules.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [ 6 | { 7 | "ts": "2004-06-16T12:00:00+00:00", 8 | "data": { 9 | "MESSAGE": "session opened for user thomas(uid=1000)", 10 | "_SYSTEMD_UNIT": "sshd", 11 | "PRIORITY": "6" 12 | } 13 | }, 14 | { 15 | "ts": "2004-06-16T12:00:00+00:00", 16 | "data": { 17 | "MESSAGE": "session opened for user blake(uid=1001)", 18 | "_SYSTEMD_UNIT": "sshd", 19 | "PRIORITY": "6" 20 | } 21 | }, 22 | { 23 | "ts": "2004-06-16T12:00:00+00:00", 24 | "data": { 25 | "MESSAGE": "session opened for user thomas(uid=1000)", 26 | "_SYSTEMD_UNIT": "sshd", 27 | "PRIORITY": "6" 28 | } 29 | }, 30 | { 31 | "ts": "2004-06-16T12:00:00+00:00", 32 | "data": { 33 | "MESSAGE": "session opened for user thomas(uid=1000)", 34 | "_SYSTEMD_UNIT": "sshd", 35 | "PRIORITY": "6" 36 | } 37 | }, 38 | { 39 | "ts": "2004-06-16T12:00:00+00:00", 40 | "data": { 41 | "MESSAGE": "session opened for user pat(uid=1002)", 42 | "_SYSTEMD_UNIT": "sshd", 43 | "PRIORITY": "6" 44 | } 45 | }, 46 | { 47 | "ts": "2004-06-16T12:00:00+00:00", 48 | "data": { 49 | "MESSAGE": "session opened for user thomas(uid=1000)", 50 | "_SYSTEMD_UNIT": "sshd", 51 | "PRIORITY": "6" 52 | } 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_config-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "polite_questions": 2.0, 7 | "ssh_sessions_blake_count": 1.0, 8 | "ssh_sessions_pat_count": 1.0, 9 | "ssh_sessions_thomas_count": 4.0 10 | } 11 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_matches_filter_rules-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "ssh_sessions_blake_count": 1.0, 7 | "ssh_sessions_pat_count": 1.0, 8 | "ssh_sessions_thomas_count": 4.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__legacy_logs_to_metrics_with_service_and_priority-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "ssh_sessions_thomas_count": 4.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__logs_to_metrics_with_dynamic_counters-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "ssh_sessions_blake_count": 1.0, 7 | "ssh_sessions_pat_count": 1.0, 8 | "ssh_sessions_thomas_count": 4.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__multiple_log_lines-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | {} 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__multiple_log_lines.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [ 6 | { 7 | "ts": "2004-06-16T12:00:00+00:00", 8 | "data": { 9 | "MESSAGE": "another message", 10 | "_SYSTEMD_UNIT": "test_service", 11 | "PRIORITY": "6" 12 | } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__multiple_log_lines_mixed_rules-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | {} 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__multiple_log_lines_mixed_rules.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [ 6 | { 7 | "ts": "2004-06-16T12:00:00+00:00", 8 | "data": { 9 | "MESSAGE": "another message", 10 | "_SYSTEMD_UNIT": "test_service", 11 | "PRIORITY": "6" 12 | } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__multiple_rules_with_extra_fields-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "foobar_hello_count": 2.0, 7 | "foobaz_goodbye_count": 1.0, 8 | "total_goodbye_count": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__multiple_rules_with_extra_fields.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [ 6 | { 7 | "ts": "2004-06-16T12:00:00+00:00", 8 | "data": { 9 | "MESSAGE": "Hello, world!", 10 | "foo": "bar" 11 | } 12 | }, 13 | { 14 | "ts": "2004-06-16T12:00:00+00:00", 15 | "data": { 16 | "MESSAGE": "Goodbye, world!", 17 | "foo": "baz" 18 | } 19 | }, 20 | { 21 | "ts": "2004-06-16T12:00:00+00:00", 22 | "data": { 23 | "MESSAGE": "Hello again, world!", 24 | "foo": "baz" 25 | } 26 | }, 27 | { 28 | "ts": "2004-06-16T12:00:00+00:00", 29 | "data": { 30 | "MESSAGE": "Hello one more time, world!", 31 | "foo": "bar" 32 | } 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__one_line_one_rule_matching-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | {} 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__one_line_one_rule_matching.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().map(|entry|\n log_filter.apply_rules(entry)).flatten().collect::>()" 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__simple_logs_to_metrics-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "first_person_log_lines": 2.0, 7 | "warning_log_lines": 2.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__simple_logs_to_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [ 6 | { 7 | "ts": "2004-06-16T12:00:00+00:00", 8 | "data": { 9 | "MESSAGE": "Knock, knock", 10 | "_SYSTEMD_UNIT": "room_service", 11 | "PRIORITY": "4" 12 | } 13 | }, 14 | { 15 | "ts": "2004-06-16T12:00:00+00:00", 16 | "data": { 17 | "MESSAGE": "What can I help you with today?", 18 | "_SYSTEMD_UNIT": "customer_service", 19 | "PRIORITY": "4" 20 | } 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__simple_with_extra_fields-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "foobar_count": 1.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__simple_with_extra_fields.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: "log_entries.into_iter().flat_map(|entry|\n log_filter.apply_rules(entry)).collect::>()" 4 | --- 5 | [] 6 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__log_filter__tests__test_default_rules-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/log_filter.rs 3 | expression: service.take_metrics().unwrap() 4 | --- 5 | { 6 | "oomkill_collectd": 1.0, 7 | "oomkill_wefaultd": 3.0, 8 | "systemd_restarts_memfaultd.service": 1.0, 9 | "systemd_restarts_wefaultd.service": 2.0 10 | } 11 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__syslog__tests__kernel_panic_rfc_3164.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/syslog.rs 3 | expression: result 4 | --- 5 | { 6 | "ts": "2025-05-15T21:30:46+00:00", 7 | "data": { 8 | "MESSAGE": "Kernel panic detected!!", 9 | "_SYSTEMD_UNIT": "kernel", 10 | "PRIORITY": "5" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__syslog__tests__multiple_messages.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/syslog.rs 3 | expression: results 4 | --- 5 | [ 6 | { 7 | "ts": "2025-05-15T14:30:45+00:00", 8 | "data": { 9 | "MESSAGE": "System started", 10 | "_PID": "1234", 11 | "_SYSTEMD_UNIT": "systemd", 12 | "PRIORITY": "2" 13 | } 14 | }, 15 | { 16 | "ts": "2025-05-15T14:30:46+00:00", 17 | "data": { 18 | "MESSAGE": "Kernel panic detected!!", 19 | "_SYSTEMD_UNIT": "kernel", 20 | "PRIORITY": "5" 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__syslog__tests__system_started_rfc_3164.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/syslog.rs 3 | expression: result 4 | --- 5 | { 6 | "ts": "2025-05-15T21:30:45+00:00", 7 | "data": { 8 | "MESSAGE": "System started", 9 | "_PID": "1234", 10 | "_SYSTEMD_UNIT": "systemd", 11 | "PRIORITY": "2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/logs/snapshots/memfaultd__logs__syslog__tests__system_started_rfc_5424.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/logs/syslog.rs 3 | expression: result 4 | --- 5 | { 6 | "ts": "2023-05-15T14:30:45+00:00", 7 | "data": { 8 | "MESSAGE": "[meta key=\"value\"] System started", 9 | "_PID": "1234", 10 | "_SYSTEMD_UNIT": "systemd", 11 | "PRIORITY": "2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/chunks.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod chunk; 5 | mod chunk_header; 6 | mod chunk_message; 7 | mod chunk_wrapper; 8 | mod crc_padded_stream; 9 | 10 | pub use chunk::Chunk; 11 | pub use chunk_message::ChunkMessage; 12 | pub use chunk_message::ChunkMessageType; 13 | pub use chunk_wrapper::ChunkWrapper; 14 | pub use crc_padded_stream::CRCPaddedStream; 15 | -------------------------------------------------------------------------------- /memfaultd/src/mar/chunks/chunk_message.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::io::{Chain, Cursor, Read}; 5 | 6 | use crate::util::io::StreamLen; 7 | 8 | /// A one-byte discriminator for the type of message being sent. 9 | #[derive(Copy, Clone, PartialEq, Eq)] 10 | #[allow(dead_code)] 11 | pub enum ChunkMessageType { 12 | Null = 0, 13 | McuCoredump = 1, 14 | Event = 2, 15 | Logs = 3, 16 | CustomDataRecording = 4, 17 | Mar = 5, 18 | } 19 | 20 | /// All data sent in chunks must be wrapped in a ChunkMessage. 21 | /// 22 | /// It adds a one-byte header indicating the type of message being sent. 23 | pub struct ChunkMessage { 24 | stream: Chain, R>, 25 | } 26 | 27 | impl ChunkMessage { 28 | pub fn new(message_type: ChunkMessageType, data: R) -> Self { 29 | Self { 30 | stream: Cursor::new([message_type as u8]).chain(data), 31 | } 32 | } 33 | } 34 | 35 | impl Read for ChunkMessage { 36 | fn read(&mut self, buf: &mut [u8]) -> std::io::Result { 37 | self.stream.read(buf) 38 | } 39 | } 40 | 41 | impl StreamLen for ChunkMessage { 42 | fn stream_len(&self) -> u64 { 43 | self.stream.stream_len() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /memfaultd/src/mar/chunks/chunk_wrapper.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::io::{Chain, Cursor, Read}; 5 | 6 | use crate::util::io::StreamLen; 7 | 8 | /// Add a little wrapper around each chunk containing an identifier and the length. 9 | /// This makes it possible to concatenate multiple chunks in one file. 10 | /// 11 | /// Format: 12 | /// - 4 identifier bytes: 'C' 'H' 'N' 'K' 13 | /// - Chunk length (4 bytes, big endian) 14 | /// 15 | /// /!\ This format is not accepted by memfault API. You have to remove that 16 | /// wrapper before sending the chunks to Memfault! 17 | pub struct ChunkWrapper { 18 | stream: Chain>, R>, 19 | } 20 | 21 | impl ChunkWrapper { 22 | pub fn new(chunk: R) -> Self { 23 | let mut header: [u8; 8] = [0; 8]; 24 | header[0..4].copy_from_slice(b"CHNK"); 25 | header[4..8].copy_from_slice(&(chunk.stream_len() as u32).to_be_bytes()); 26 | 27 | Self { 28 | stream: Cursor::new(header.to_vec()).chain(chunk), 29 | } 30 | } 31 | } 32 | 33 | impl Read for ChunkWrapper { 34 | fn read(&mut self, buf: &mut [u8]) -> std::io::Result { 35 | self.stream.read(buf) 36 | } 37 | } 38 | 39 | impl StreamLen for ChunkWrapper { 40 | fn stream_len(&self) -> u64 { 41 | self.stream.stream_len() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /memfaultd/src/mar/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | pub mod clean; 5 | pub mod manifest; 6 | pub mod mar_entry; 7 | pub mod mar_entry_builder; 8 | pub mod upload; 9 | 10 | pub use clean::*; 11 | pub use manifest::*; 12 | pub use mar_entry::*; 13 | pub use mar_entry_builder::*; 14 | pub use upload::*; 15 | 16 | mod chunks; 17 | mod export; 18 | mod export_format; 19 | 20 | pub use chunks::{Chunk, ChunkMessage, ChunkMessageType, ChunkWrapper}; 21 | pub use export::{MarExportHandler, EXPORT_MAR_URL}; 22 | pub use export_format::ExportFormat; 23 | 24 | #[cfg(test)] 25 | mod test_utils; 26 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__deletes_mar_entry_when_over_max_count.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 2.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 2.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 2.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__keeps_mar_entry_when_max_age_is_zero.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__keeps_mar_entry_within_max_age.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__keeps_recent_mar_entry.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__keeps_recent_unfinished_mar_entry.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__max_entries_0.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 2.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 2.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 2.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__max_entries_equal.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 2.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 2.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 2.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__max_entries_greater_than.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 0.0, 10 | "MemfaultSdkMetric_mar_entry_count": 2.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 2.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 2.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__max_entries_less_than.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 2.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 2.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 2.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_entries_exceeding_max_total_size_by_age.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 2.0, 10 | "MemfaultSdkMetric_mar_entry_count": 4.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 4.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 4.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_entries_exceeding_min_headroom_size_by_age.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 2.0, 10 | "MemfaultSdkMetric_mar_entry_count": 4.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 4.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 4.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_mar_entry_exceeding_max_age.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 2.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 2.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 2.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_mar_entry_exceeding_max_total_size.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_mar_entry_exceeding_min_headroom.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_mar_entry_exceeding_min_headroom_inodes.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_oldest_mar_entry_exceeding_max_total_size_when_multiple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 3.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 3.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 3.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__clean__test__removes_unfinished_mar_entry_exceeding_max_total_size.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/clean.rs 3 | expression: metrics_service.take_metrics().unwrap() 4 | --- 5 | { 6 | "MemfaultSdkMetric_mar_clean_duration_seconds": "", 7 | "MemfaultSdkMetric_mar_clean_duration_seconds_max": "", 8 | "MemfaultSdkMetric_mar_clean_duration_seconds_min": "", 9 | "MemfaultSdkMetric_mar_entries_deleted": 1.0, 10 | "MemfaultSdkMetric_mar_entry_count": 1.0, 11 | "MemfaultSdkMetric_mar_entry_count_max": 1.0, 12 | "MemfaultSdkMetric_mar_entry_count_min": 1.0 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__attributes.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "1970-01-01T00:00:04.321Z", 9 | "uptime_ms": 800000, 10 | "linux_boot_id": "230295cb-04d4-40b8-8624-ec37089b9b75", 11 | "elapsed_realtime_ms": 900000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "INSERT_PROJECT_KEY_HERE", 16 | "hardware_version": "evt", 17 | "software_version": "1.0.0", 18 | "software_type": "linux-build", 19 | "device_serial": "DEMOSERIAL" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "device-attributes", 28 | "metadata": { 29 | "attributes": [ 30 | { 31 | "string_key": "my_string", 32 | "value": "foo" 33 | }, 34 | { 35 | "string_key": "my_integer", 36 | "value": 123 37 | }, 38 | { 39 | "string_key": "my_float", 40 | "value": 123.456 41 | }, 42 | { 43 | "string_key": "my_bool", 44 | "value": true 45 | } 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__coredump-gzip.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "elf-coredump", 28 | "metadata": { 29 | "coredump_file_name": "/tmp/core.elf", 30 | "compression": "gzip" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__coredump-none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "elf-coredump", 28 | "metadata": { 29 | "coredump_file_name": "/tmp/core.elf" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__device_config.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "device-config", 28 | "metadata": { 29 | "revision": 42 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__elf_coredump.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "1970-01-01T00:00:04.321Z", 9 | "uptime_ms": 800000, 10 | "linux_boot_id": "230295cb-04d4-40b8-8624-ec37089b9b75", 11 | "elapsed_realtime_ms": 900000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "INSERT_PROJECT_KEY_HERE", 16 | "hardware_version": "evt", 17 | "software_version": "1.0.0", 18 | "software_type": "linux-build", 19 | "device_serial": "DEMOSERIAL" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "elf-coredump", 28 | "metadata": { 29 | "coredump_file_name": "core-da01317a-902f-48f8-8c3f-aabf8b14facc.elf.gz", 30 | "compression": "gzip" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__log-none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-logs", 28 | "metadata": { 29 | "format": { 30 | "id": "v1", 31 | "serialization": "json-lines" 32 | }, 33 | "log_file_name": "/var/log/syslog", 34 | "cid": { 35 | "uuid": "99686390-a728-11ed-a68b-e7ff3cd0c7e7" 36 | }, 37 | "next_cid": { 38 | "uuid": "9e1ece10-a728-11ed-918e-5be35a10c7e7" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__log-zlib.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-logs", 28 | "metadata": { 29 | "format": { 30 | "id": "v1", 31 | "serialization": "json-lines" 32 | }, 33 | "log_file_name": "/var/log/syslog", 34 | "compression": "zlib", 35 | "cid": { 36 | "uuid": "99686390-a728-11ed-a68b-e7ff3cd0c7e7" 37 | }, 38 | "next_cid": { 39 | "uuid": "9e1ece10-a728-11ed-918e-5be35a10c7e7" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__reboot.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2023-05-24T18:20:21.371852623Z", 9 | "uptime_ms": 17445527, 10 | "linux_boot_id": "48af0b97-79c3-4e95-ba80-8c436b4b9e8f", 11 | "elapsed_realtime_ms": 17445527, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "INSERT_PROJECT_KEY_HERE", 16 | "hardware_version": "qemuarm64", 17 | "software_version": "0.0.1", 18 | "software_type": "main", 19 | "device_serial": "DEMOSERIAL" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-reboot", 28 | "metadata": { 29 | "reason": 3 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__serialization_of_custom_reboot.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-reboot", 28 | "metadata": { 29 | "reason": { 30 | "unexpected": false, 31 | "name": "CustomRebootReason" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__serialization_of_custom_unexpected_reboot.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-reboot", 28 | "metadata": { 29 | "reason": { 30 | "unexpected": true, 31 | "name": "CustomUnexpectedRebootReason" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__serialization_of_device_attributes.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "device-attributes", 28 | "metadata": { 29 | "attributes": [ 30 | { 31 | "string_key": "my_string", 32 | "value": "foo" 33 | }, 34 | { 35 | "string_key": "my_int", 36 | "value": 123 37 | }, 38 | { 39 | "string_key": "my_float", 40 | "value": 123.456 41 | }, 42 | { 43 | "string_key": "my_bool", 44 | "value": true 45 | } 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__serialization_of_device_configc.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "device-config", 28 | "metadata": { 29 | "revision": 42 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__serialization_of_linux_heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-metric-report", 28 | "metadata": { 29 | "metrics": { 30 | "n1": 1.0, 31 | "n2": 42.0 32 | }, 33 | "duration_ms": 42000, 34 | "boottime_duration_ms": 42000, 35 | "report_type": "heartbeat" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /memfaultd/src/mar/snapshots/memfaultd__mar__manifest__tests__serialization_of_reboot.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/mar/manifest.rs 3 | expression: manifest 4 | --- 5 | { 6 | "schema_version": 1, 7 | "collection_time": { 8 | "timestamp": "2012-04-12T17:00:00Z", 9 | "uptime_ms": 10000, 10 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 11 | "elapsed_realtime_ms": 10000, 12 | "boot_count": 0 13 | }, 14 | "device": { 15 | "project_key": "abcd", 16 | "hardware_version": "DVT", 17 | "software_version": "1.0.0", 18 | "software_type": "test", 19 | "device_serial": "001" 20 | }, 21 | "producer": { 22 | "id": "memfaultd", 23 | "version": "tests", 24 | "os_version": "tests", 25 | "os_name": "tests" 26 | }, 27 | "type": "linux-reboot", 28 | "metadata": { 29 | "reason": 1 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /memfaultd/src/mar/test-manifests/attributes.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": 1, 3 | "collection_time": { 4 | "timestamp": "1970-01-01T00:00:04.321Z", 5 | "uptime_ms": 800000, 6 | "elapsed_realtime_ms": 900000, 7 | "linux_boot_id": "230295cb-04d4-40b8-8624-ec37089b9b75", 8 | "boot_count": 0 9 | }, 10 | "type": "device-attributes", 11 | "device": { 12 | "project_key": "INSERT_PROJECT_KEY_HERE", 13 | "hardware_version": "evt", 14 | "software_version": "1.0.0", 15 | "software_type": "linux-build", 16 | "device_serial": "DEMOSERIAL" 17 | }, 18 | "metadata": { 19 | "attributes": [ 20 | { 21 | "string_key": "my_string", 22 | "value": "foo" 23 | }, 24 | { 25 | "string_key": "my_integer", 26 | "value": 123 27 | }, 28 | { 29 | "string_key": "my_float", 30 | "value": 123.456 31 | }, 32 | { 33 | "string_key": "my_bool", 34 | "value": true 35 | } 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /memfaultd/src/mar/test-manifests/device_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": 1, 3 | "collection_time": { 4 | "timestamp": "2012-04-12T17:00:00Z", 5 | "uptime_ms": 10000, 6 | "linux_boot_id": "413554b8-a727-11ed-b307-0317a0ffbea7", 7 | "elapsed_realtime_ms": 10000, 8 | "boot_count": 0 9 | }, 10 | "device": { 11 | "project_key": "abcd", 12 | "hardware_version": "DVT", 13 | "software_version": "1.0.0", 14 | "software_type": "test", 15 | "device_serial": "001" 16 | }, 17 | "type": "device-config", 18 | "metadata": { 19 | "revision": 42 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /memfaultd/src/mar/test-manifests/elf_coredump.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": 1, 3 | "collection_time": { 4 | "timestamp": "1970-01-01T00:00:04.321Z", 5 | "uptime_ms": 800000, 6 | "elapsed_realtime_ms": 900000, 7 | "linux_boot_id": "230295cb-04d4-40b8-8624-ec37089b9b75", 8 | "boot_count": 0 9 | }, 10 | "device": { 11 | "project_key": "INSERT_PROJECT_KEY_HERE", 12 | "hardware_version": "evt", 13 | "software_version": "1.0.0", 14 | "software_type": "linux-build", 15 | "device_serial": "DEMOSERIAL" 16 | }, 17 | "type": "elf-coredump", 18 | "metadata": { 19 | "coredump_file_name": "core-da01317a-902f-48f8-8c3f-aabf8b14facc.elf.gz", 20 | "compression": "gzip" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /memfaultd/src/mar/test-manifests/log.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": 1, 3 | "collection_time": { 4 | "timestamp": "1970-01-01T00:00:04.321Z", 5 | "uptime_ms": 800000, 6 | "elapsed_realtime_ms": 900000, 7 | "linux_boot_id": "230295cb-04d4-40b8-8624-ec37089b9b75", 8 | "boot_count": 0 9 | }, 10 | "type": "linux-logs", 11 | "device": { 12 | "project_key": "INSERT_PROJECT_KEY_HERE", 13 | "hardware_version": "evt", 14 | "software_version": "1.0.0", 15 | "software_type": "linux-build", 16 | "device_serial": "DEMOSERIAL" 17 | }, 18 | "metadata": { 19 | "format": { "id": "v1", "serialization": "json-lines" }, 20 | "producer": { "id": "memfaultd", "version": "2.0.0" }, 21 | "log_file_name": "logs.txt", 22 | "cid": { "uuid": "271e5249-1e3f-4c89-b4a5-ed96cc8f42a7" }, 23 | "next_cid": { "uuid": "4276a26b-ba89-4c57-832f-d9e90e9629dd" } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /memfaultd/src/mar/test-manifests/reboot.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": 1, 3 | "collection_time": { 4 | "timestamp": "2023-05-24T18:20:21.371852623Z", 5 | "uptime_ms": 17445527, 6 | "linux_boot_id": "48af0b97-79c3-4e95-ba80-8c436b4b9e8f", 7 | "elapsed_realtime_ms": 17445527, 8 | "boot_count": 0 9 | }, 10 | "device": { 11 | "project_key": "INSERT_PROJECT_KEY_HERE", 12 | "hardware_version": "qemuarm64", 13 | "software_version": "0.0.1", 14 | "software_type": "main", 15 | "device_serial": "DEMOSERIAL" 16 | }, 17 | "type": "linux-reboot", 18 | "metadata": { 19 | "reason": 3 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/battery/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod battery_reading_handler; 5 | pub use battery_reading_handler::BatteryReadingHandler; 6 | 7 | mod battery_monitor; 8 | pub use battery_monitor::BatteryMonitor; 9 | pub use battery_monitor::BatteryMonitorReading; 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/battery/snapshots/memfaultd__metrics__battery__battery_reading_handler__tests__charging_then_discharging.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/battery/battery_reading_handler.rs 3 | expression: "&sorted_metrics" 4 | --- 5 | { 6 | "battery_discharge_duration_ms": 30000.0, 7 | "battery_soc_pct": 0.0, 8 | "battery_soc_pct_drop": 10.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/battery/snapshots/memfaultd__metrics__battery__battery_reading_handler__tests__handle_push.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/battery/battery_reading_handler.rs 3 | expression: "serde_json::to_string_pretty(&sorted_metrics).expect(\"metric_store should be serializable\")" 4 | --- 5 | { 6 | "battery_discharge_duration_ms": 0.0, 7 | "battery_soc_pct": null, 8 | "battery_soc_pct_drop": 0.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/battery/snapshots/memfaultd__metrics__battery__battery_reading_handler__tests__non_integer_percentages.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/battery/battery_reading_handler.rs 3 | expression: "&sorted_metrics" 4 | --- 5 | { 6 | "battery_discharge_duration_ms": 30000.0, 7 | "battery_soc_pct": 0.0, 8 | "battery_soc_pct_drop": 10.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/battery/snapshots/memfaultd__metrics__battery__battery_reading_handler__tests__nonconsecutive_discharges.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/battery/battery_reading_handler.rs 3 | expression: "&sorted_metrics" 4 | --- 5 | { 6 | "battery_discharge_duration_ms": 60000.0, 7 | "battery_soc_pct": 0.0, 8 | "battery_soc_pct_drop": 60.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod connectivity_monitor; 5 | pub use connectivity_monitor::ConnectivityMonitor; 6 | 7 | mod report_sync_event_handler; 8 | pub use report_sync_event_handler::ReportSyncEventHandler; 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/snapshots/memfaultd__metrics__connectivity__connectivity_monitor__tests__fully_disconnected.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/connectivity/connectivity_monitor.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "connectivity_connected_time_ms": 0.0, 7 | "connectivity_expected_time_ms": 60000.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/snapshots/memfaultd__metrics__connectivity__connectivity_monitor__tests__half_connected_half_disconnected.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/connectivity/connectivity_monitor.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "connectivity_connected_time_ms": 30000.0, 7 | "connectivity_expected_time_ms": 60000.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/snapshots/memfaultd__metrics__connectivity__connectivity_monitor__tests__while_connected.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/connectivity/connectivity_monitor.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "connectivity_connected_time_ms": 30000.0, 7 | "connectivity_expected_time_ms": 30000.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/snapshots/memfaultd__metrics__connectivity__report_sync_event_handler__tests__handle_multiple_sync_events.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/connectivity/report_sync_event_handler.rs 3 | expression: "serde_json::to_string_pretty(&sorted_metrics).expect(\"metric_store should be serializable\")" 4 | --- 5 | { 6 | "sync_failure": 10.0, 7 | "sync_successful": 90.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/snapshots/memfaultd__metrics__connectivity__report_sync_event_handler__tests__handle_sync_failure.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/connectivity/report_sync_event_handler.rs 3 | expression: "serde_json::to_string_pretty(&metrics).expect(\"metric_store should be serializable\")" 4 | --- 5 | { 6 | "sync_failure": 1.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/connectivity/snapshots/memfaultd__metrics__connectivity__report_sync_event_handler__tests__handle_sync_success.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/connectivity/report_sync_event_handler.rs 3 | expression: "serde_json::to_string_pretty(&metrics).expect(\"metric_store should be serializable\")" 4 | --- 5 | { 6 | "sync_successful": 1.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod report; 5 | pub use report::{HrtReport, HRT_DEFAULT_MAX_SAMPLES_PER_MIN}; 6 | 7 | mod schema; 8 | pub use schema::write_report_to_disk; 9 | // Export for use in tests 10 | #[cfg(test)] 11 | pub use schema::HighResTelemetryV1; 12 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/snapshots/memfaultd__metrics__hrt__schema__test__cdr_write-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/hrt/schema.rs 3 | expression: manifest.metadata 4 | --- 5 | { 6 | "type": "custom-data-recording", 7 | "metadata": { 8 | "start_time": { 9 | "timestamp": "1991-03-25T00:00:00Z" 10 | }, 11 | "duration_ms": 0, 12 | "mimetypes": [ 13 | "application/vnd.memfault.hrt.v1" 14 | ], 15 | "reason": "hrt", 16 | "recording_file_name": "hrt.json.gz", 17 | "compression": "gzip" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/snapshots/memfaultd__metrics__hrt__schema__test__cdr_write.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/hrt/schema.rs 3 | expression: json!(hrt) 4 | --- 5 | { 6 | "duration_ms": 0, 7 | "producer": { 8 | "id": "memfaultd", 9 | "version": "1.2.3" 10 | }, 11 | "rollups": [ 12 | { 13 | "data": [ 14 | { 15 | "t": 1234, 16 | "value": 567.0 17 | }, 18 | { 19 | "t": 5678, 20 | "value": 123.0 21 | } 22 | ], 23 | "metadata": { 24 | "data_type": "double", 25 | "internal": false, 26 | "metric_type": "counter", 27 | "string_key": "test" 28 | } 29 | } 30 | ], 31 | "schema_version": 1, 32 | "start_time": 669859200000 33 | } 34 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/snapshots/memfaultd__metrics__hrt__schema__test__counter.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/hrt/schema.rs 3 | expression: json!(datum) 4 | --- 5 | { 6 | "t": 1234, 7 | "value": 123.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/snapshots/memfaultd__metrics__hrt__schema__test__gauge.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/hrt/schema.rs 3 | expression: json!(datum) 4 | --- 5 | { 6 | "t": 1234, 7 | "value": 123.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/snapshots/memfaultd__metrics__hrt__schema__test__histogram.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/hrt/schema.rs 3 | expression: json!(datum) 4 | --- 5 | { 6 | "t": 1234, 7 | "value": 123.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/hrt/snapshots/memfaultd__metrics__hrt__schema__test__serialization.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/hrt/schema.rs 3 | expression: json!(hrt) 4 | --- 5 | { 6 | "duration_ms": 0, 7 | "producer": { 8 | "id": "memfaultd", 9 | "version": "1.2.3" 10 | }, 11 | "rollups": [ 12 | { 13 | "data": [ 14 | { 15 | "t": 1010, 16 | "value": 220.0 17 | } 18 | ], 19 | "metadata": { 20 | "data_type": "double", 21 | "internal": false, 22 | "metric_type": "counter", 23 | "string_key": "test" 24 | } 25 | } 26 | ], 27 | "schema_version": 1, 28 | "start_time": 669859200000 29 | } 30 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/internal_metrics.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | // MAR cleaner metrics 5 | pub const INTERNAL_METRIC_MAR_ENTRY_COUNT: &str = "MemfaultSdkMetric_mar_entry_count"; 6 | pub const INTERNAL_METRIC_MAR_CLEANER_DURATION: &str = 7 | "MemfaultSdkMetric_mar_clean_duration_seconds"; 8 | pub const INTERNAL_METRIC_MAR_ENTRIES_DELETED: &str = "MemfaultSdkMetric_mar_entries_deleted"; 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/metric_value.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use eyre::Result; 5 | use serde::{Deserialize, Serialize, Serializer}; 6 | 7 | #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] 8 | pub struct Histogram { 9 | pub min: f64, 10 | pub mean: f64, 11 | pub max: f64, 12 | } 13 | 14 | impl Histogram { 15 | pub fn min(&self) -> MetricValue { 16 | MetricValue::Number(self.min) 17 | } 18 | 19 | pub fn avg(&self) -> MetricValue { 20 | MetricValue::Number(self.mean) 21 | } 22 | 23 | pub fn max(&self) -> MetricValue { 24 | MetricValue::Number(self.max) 25 | } 26 | } 27 | 28 | pub fn construct_histogram_value(min: f64, mean: f64, max: f64) -> Histogram { 29 | Histogram { min, mean, max } 30 | } 31 | 32 | #[derive(Clone, Debug, PartialEq, Deserialize)] 33 | #[serde(untagged)] 34 | pub enum MetricValue { 35 | Number(f64), 36 | String(String), 37 | Histogram(Histogram), 38 | Bool(bool), 39 | } 40 | 41 | impl Serialize for MetricValue { 42 | fn serialize(&self, serializer: S) -> Result 43 | where 44 | S: Serializer, 45 | { 46 | match self { 47 | MetricValue::Number(v) => serializer.serialize_f64(*v), 48 | MetricValue::String(v) => serializer.serialize_str(v.as_str()), 49 | MetricValue::Histogram(histo) => histo.serialize(serializer), 50 | MetricValue::Bool(v) => serializer.serialize_bool(*v), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__crashfree_interval__tests__process_crash_counter.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/crashfree_interval.rs 3 | expression: metrics_mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "operational_crashes": 4.0, 7 | "operational_crashes_collectd": 1.0, 8 | "operational_crashes_memfaultd": 3.0, 9 | "operational_crashfree_hours": 1.0, 10 | "operational_hours": 1.0 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_1.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "bar": 2.0, 7 | "baz": 3.0, 8 | "foo": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "cpu_usage_memfaultd_pct": 2.0, 7 | "cpu_usage_memfaultd_pct_max": 3.0, 8 | "cpu_usage_memfaultd_pct_min": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "foo": 1.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_4.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "memory_pct": 1.5, 7 | "memory_pct_max": 2.0, 8 | "memory_pct_min": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_5.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "memory_systemd_pct": 1.6666666666666667, 7 | "memory_systemd_pct_max": 2.0, 8 | "memory_systemd_pct_min": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_6.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "interface/eth0/bytes_per_second/rx": 1.6666666666666667, 7 | "interface/eth0/bytes_per_second/rx_max": 2.0, 8 | "interface/eth0/bytes_per_second/rx_min": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__heartbeat_report_7.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "interface/eth0/packets_per_second/rx": 1.6666666666666667 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__overwrite_previous_reading.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | snapshot_kind: text 5 | --- 6 | { 7 | "bar": true, 8 | "foo": false 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__session_report_1.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "baz": 3.0, 7 | "foo": 1.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__session_report_2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "foo": 2.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__session_report_3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "foo": 1.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__session_report_4.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "foo": 1.5 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__session_report_5.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "baz": 2.0, 7 | "foo": 1.5 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report__tests__session_report_6.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report.rs 3 | expression: sorted_metrics 4 | --- 5 | { 6 | "operational_crashes": 2.0, 7 | "operational_crashes_memfaultd": 5.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__daily-heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 3.5, 10 | "foo": 5.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": "daily-heartbeat" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 3.5, 10 | "foo": 5.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": "heartbeat" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.daily_heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "baz": 3.0, 11 | "foo": 1.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": "daily-heartbeat" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "baz": 3.0, 11 | "foo": 1.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": "heartbeat" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.test-session-all-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "baz": 3.0, 11 | "foo": 1.0, 12 | "operational_crashes": 0.0 13 | }, 14 | "duration_ms": 0, 15 | "boottime_duration_ms": 0, 16 | "report_type": { 17 | "session": "test-session-all-metrics" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_1.test-session-some-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "foo": 1.0, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session-some-metrics" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.daily_heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 2.0 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "daily-heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 2.0 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.test-session-all-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 2.0, 10 | "operational_crashes": 0.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": { 15 | "session": "test-session-all-metrics" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_2.test-session-some-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 2.0, 10 | "operational_crashes": 0.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": { 15 | "session": "test-session-some-metrics" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.daily_heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.0 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "daily-heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.0 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.test-session-all-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.0, 10 | "operational_crashes": 0.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": { 15 | "session": "test-session-all-metrics" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_3.test-session-some-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.0, 10 | "operational_crashes": 0.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": { 15 | "session": "test-session-some-metrics" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.daily_heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "baz": 1.5, 10 | "foo": 1.5 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": "daily-heartbeat" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "baz": 1.5, 10 | "foo": 1.5 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": "heartbeat" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.test-session-all-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "baz": 1.5, 10 | "foo": 1.5, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session-all-metrics" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_4.test-session-some-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.5, 10 | "operational_crashes": 0.0 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": { 15 | "session": "test-session-some-metrics" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.daily_heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "foo": 1.5 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": "daily-heartbeat" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.heartbeat.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "foo": 1.5 11 | }, 12 | "duration_ms": 0, 13 | "boottime_duration_ms": 0, 14 | "report_type": "heartbeat" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.test-session-all-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "foo": 1.5, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session-all-metrics" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_and_sessions_report_5.test-session-some-metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "foo": 1.5, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session-some-metrics" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_report_1.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 2.0, 10 | "baz": 3.0, 11 | "foo": 1.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": "heartbeat" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_report_2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 2.0 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_report_3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.0 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_report_4.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.5 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__heartbeat_report_5.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "foo": 1.6666666666666667 10 | }, 11 | "duration_ms": 0, 12 | "boottime_duration_ms": 0, 13 | "report_type": "heartbeat" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__hrt_when_enabled.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: hrt_report_serialized 4 | --- 5 | { 6 | "schema_version": 1, 7 | "producer": { 8 | "id": "memfaultd", 9 | "version": "[version]" 10 | }, 11 | "start_time": "[start_time]", 12 | "duration_ms": "[duration]", 13 | "rollups": [ 14 | { 15 | "metadata": { 16 | "string_key": "bar", 17 | "metric_type": "gauge", 18 | "data_type": "double", 19 | "internal": false 20 | }, 21 | "data": [ 22 | { 23 | "t": "[timestamp]", 24 | "value": 2.0 25 | } 26 | ] 27 | }, 28 | { 29 | "metadata": { 30 | "string_key": "baz", 31 | "metric_type": "gauge", 32 | "data_type": "double", 33 | "internal": false 34 | }, 35 | "data": [ 36 | { 37 | "t": "[timestamp]", 38 | "value": 3.0 39 | } 40 | ] 41 | }, 42 | { 43 | "metadata": { 44 | "string_key": "foo", 45 | "metric_type": "gauge", 46 | "data_type": "double", 47 | "internal": false 48 | }, 49 | "data": [ 50 | { 51 | "t": "[timestamp]", 52 | "value": 1.0 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__process_metrics_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: metrics 4 | --- 5 | { 6 | "memory_foo_pct": 2.0, 7 | "memory_foo_pct_max": 2.0, 8 | "memory_foo_pct_min": 2.0, 9 | "memory_memfaultd_pct": 2.0, 10 | "memory_memfaultd_pct_max": 2.0, 11 | "memory_memfaultd_pct_min": 2.0, 12 | "memory_systemd_pct": 1.0, 13 | "memory_systemd_pct_max": 1.0, 14 | "memory_systemd_pct_min": 1.0, 15 | "operational_crashes": 0.0 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__start_session_twice.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.unwrap().get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 3.5, 10 | "foo": 5.0, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session-start-twice" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__system_and_process_metrics_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: metrics 4 | --- 5 | { 6 | "cpu_usage_memfaultd_pct": 2.0, 7 | "cpu_usage_memfaultd_pct_max": 2.0, 8 | "cpu_usage_memfaultd_pct_min": 2.0, 9 | "foo": 1.0, 10 | "memory_pct": 3.0, 11 | "memory_pct_max": 3.0, 12 | "memory_pct_min": 3.0, 13 | "operational_crashes": 0.0 14 | } 15 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metric_report_manager__tests__test-session.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metric_report_manager.rs 3 | expression: builder.get_metadata() 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 3.5, 10 | "foo": 5.0, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__metrics_event_handler__test__handle_request.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/metrics_event_handler.rs 3 | expression: metrics 4 | snapshot_kind: text 5 | --- 6 | { 7 | "Carlton": 2.0, 8 | "Daisy": 1.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__session_event_handler__tests__end_with_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/session_event_handler.rs 3 | expression: manifest.metadata 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 3.0, 10 | "foo": 1.0, 11 | "operational_crashes": 0.0 12 | }, 13 | "duration_ms": 0, 14 | "boottime_duration_ms": 0, 15 | "report_type": { 16 | "session": "test-session" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__session_event_handler__tests__start_then_stop.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/session_event_handler.rs 3 | expression: manifest.metadata 4 | --- 5 | { 6 | "type": "linux-metric-report", 7 | "metadata": { 8 | "metrics": { 9 | "bar": 20.0, 10 | "baz": "test-tag", 11 | "foo": 100.0, 12 | "operational_crashes": 0.0 13 | }, 14 | "duration_ms": 0, 15 | "boottime_duration_ms": 0, 16 | "report_type": { 17 | "session": "test-session" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__session_event_handler__tests__start_twice_without_stop_session.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/session_event_handler.rs 3 | expression: fixture.take_session_metrics() 4 | --- 5 | { 6 | "bar": 11.0, 7 | "foo": 5.5, 8 | "operational_crashes": 0.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__session_event_handler__tests__start_with_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/session_event_handler.rs 3 | expression: metrics 4 | --- 5 | { 6 | "bar": 4.0, 7 | "baz": "test-tag", 8 | "foo": 1.0, 9 | "operational_crashes": 0.0 10 | } 11 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/snapshots/memfaultd__metrics__session_event_handler__tests__start_without_stop_session.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/session_event_handler.rs 3 | expression: fixture.take_session_metrics() 4 | --- 5 | { 6 | "bar": 2.0, 7 | "foo": 1.0, 8 | "operational_crashes": 0.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_counter_aggregation.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: metrics 4 | --- 5 | { 6 | "test_counter": 2.0 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_counter_and_gauge_aggregation.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: metrics 4 | --- 5 | { 6 | "test_counter": 2.0, 7 | "test_gauge": 10.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_counter_and_legacy_gauge_aggregation.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: fixture_legacy_gauge_aggregation.mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "test_counter": 2.0, 7 | "test_gauge": 6.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_histogram_aggregation.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: fixture.mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "test_another_histo": 510.0, 7 | "test_histo": 100.0, 8 | "test_one_more_histo": 35.0 9 | } 10 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_legacy_gauge_aggregation.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: fixture_legacy_gauge_aggregation.mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "test-gauge": 1.5 7 | } 8 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_simple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: metrics 4 | --- 5 | { 6 | "test_counter": 1.0, 7 | "test_gauge": 2.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/statsd_server/snapshots/memfaultd__metrics__statsd_server__test__test_simple_dashes.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/statsd_server/mod.rs 3 | expression: fixture.mock.take_metrics().unwrap() 4 | --- 5 | { 6 | "test-counter": 1.0, 7 | "test-gauge": 2.0 8 | } 9 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__cpu__test__basic_delta_a_b_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/cpu.rs 3 | expression: result_b 4 | --- 5 | [ 6 | { 7 | "name": "cpu/cpu/percent/idle", 8 | "value": { 9 | "Histogram": { 10 | "value": 0.19231, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "cpu/cpu/percent/iowait", 17 | "value": { 18 | "Histogram": { 19 | "value": 0.0, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "cpu/cpu/percent/irq", 26 | "value": { 27 | "Histogram": { 28 | "value": 0.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "cpu/cpu/percent/nice", 35 | "value": { 36 | "Histogram": { 37 | "value": 2.88462, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | }, 42 | { 43 | "name": "cpu/cpu/percent/softirq", 44 | "value": { 45 | "Histogram": { 46 | "value": 0.0, 47 | "timestamp": "[timestamp]" 48 | } 49 | } 50 | }, 51 | { 52 | "name": "cpu/cpu/percent/system", 53 | "value": { 54 | "Histogram": { 55 | "value": 0.76923, 56 | "timestamp": "[timestamp]" 57 | } 58 | } 59 | }, 60 | { 61 | "name": "cpu/cpu/percent/user", 62 | "value": { 63 | "Histogram": { 64 | "value": 96.15385, 65 | "timestamp": "[timestamp]" 66 | } 67 | } 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__cpu__test__basic_delta_b_c_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/cpu.rs 3 | expression: result_c 4 | --- 5 | [ 6 | { 7 | "name": "cpu/cpu/percent/idle", 8 | "value": { 9 | "Histogram": { 10 | "value": 0.74349, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "cpu/cpu/percent/iowait", 17 | "value": { 18 | "Histogram": { 19 | "value": 0.37175, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "cpu/cpu/percent/irq", 26 | "value": { 27 | "Histogram": { 28 | "value": 0.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "cpu/cpu/percent/nice", 35 | "value": { 36 | "Histogram": { 37 | "value": 66.9145, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | }, 42 | { 43 | "name": "cpu/cpu/percent/softirq", 44 | "value": { 45 | "Histogram": { 46 | "value": 0.0, 47 | "timestamp": "[timestamp]" 48 | } 49 | } 50 | }, 51 | { 52 | "name": "cpu/cpu/percent/system", 53 | "value": { 54 | "Histogram": { 55 | "value": 13.3829, 56 | "timestamp": "[timestamp]" 57 | } 58 | } 59 | }, 60 | { 61 | "name": "cpu/cpu/percent/user", 62 | "value": { 63 | "Histogram": { 64 | "value": 18.58736, 65 | "timestamp": "[timestamp]" 66 | } 67 | } 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__cpu__test__test_basic_line.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/cpu.rs 3 | expression: "CpuMetricCollector::parse_proc_stat_line_cpu(proc_stat_line).unwrap()" 4 | --- 5 | [ 6 | 1000, 7 | 5, 8 | 0, 9 | 0, 10 | 2, 11 | 0, 12 | 0 13 | ] 14 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__disk__test__get_disk_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/disk.rs 3 | expression: metrics 4 | snapshot_kind: text 5 | --- 6 | [ 7 | { 8 | "name": "diskstats/mmcblk0/lifetime_pct", 9 | "value": { 10 | "Gauge": { 11 | "value": 90.0, 12 | "timestamp": "[timestamp]" 13 | } 14 | } 15 | }, 16 | { 17 | "name": "diskstats/mmcblk0/bytes_written", 18 | "value": { 19 | "Counter": { 20 | "value": 512000.0, 21 | "timestamp": "[timestamp]" 22 | } 23 | } 24 | }, 25 | { 26 | "name": "diskstats/mmcblk0/name", 27 | "value": { 28 | "ReportTag": { 29 | "value": "SG123", 30 | "timestamp": "[timestamp]" 31 | } 32 | } 33 | }, 34 | { 35 | "name": "diskstats/mmcblk0/manufacturer_id", 36 | "value": { 37 | "ReportTag": { 38 | "value": "0x00015", 39 | "timestamp": "[timestamp]" 40 | } 41 | } 42 | }, 43 | { 44 | "name": "diskstats/mmcblk0/total_size_bytes", 45 | "value": { 46 | "Gauge": { 47 | "value": 51200.0, 48 | "timestamp": "[timestamp]" 49 | } 50 | } 51 | }, 52 | { 53 | "name": "diskstats/mmcblk0/manufacture_date", 54 | "value": { 55 | "ReportTag": { 56 | "value": "11/2023", 57 | "timestamp": "[timestamp]" 58 | } 59 | } 60 | } 61 | ] 62 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__disk_space__test__initialize_and_calc_disk_space_for_mounts-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/disk_space.rs 3 | expression: metrics 4 | --- 5 | [ 6 | { 7 | "name": "disk_space/sda1/free_bytes", 8 | "value": { 9 | "Histogram": { 10 | "value": 1171456.0, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "disk_space/sda1/used_bytes", 17 | "value": { 18 | "Histogram": { 19 | "value": 3022848.0, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "disk_space/sda2/free_bytes", 26 | "value": { 27 | "Histogram": { 28 | "value": 1171456.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "disk_space/sda2/used_bytes", 35 | "value": { 36 | "Histogram": { 37 | "value": 3022848.0, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__disk_space__test__initialize_and_calc_disk_space_for_mounts.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/disk_space.rs 3 | expression: disk_space_collector.mounts 4 | --- 5 | [ 6 | { 7 | "device": "/dev/sda1", 8 | "mount_point": "/" 9 | }, 10 | { 11 | "device": "/dev/sda2", 12 | "mount_point": "/media" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__diskstats__test__basic_diskstats_calc.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/diskstats.rs 3 | expression: result_b 4 | snapshot_kind: text 5 | --- 6 | [ 7 | { 8 | "name": "diskstats/sda/reads_per_second", 9 | "value": { 10 | "Histogram": { 11 | "value": 10.0, 12 | "timestamp": "[timestamp]" 13 | } 14 | } 15 | }, 16 | { 17 | "name": "diskstats/sda/writes_per_second", 18 | "value": { 19 | "Histogram": { 20 | "value": 20.0, 21 | "timestamp": "[timestamp]" 22 | } 23 | } 24 | } 25 | ] 26 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__diskstats__test__basic_diskstats_line.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/diskstats.rs 3 | expression: disk_stats 4 | --- 5 | [ 6 | 57839, 7 | 46346, 8 | 3776180, 9 | 24107, 10 | 2868024, 11 | 458991, 12 | 39327918, 13 | 1458693 14 | ] 15 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__diskstats__test__from_qemu.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/diskstats.rs 3 | expression: disk_stats 4 | --- 5 | [ 6 | 59, 7 | 125, 8 | 775, 9 | 15, 10 | 2, 11 | 0, 12 | 2, 13 | 0 14 | ] 15 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__memory__test__get_memory_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/memory.rs 3 | expression: "MemInfoParserImpl::parse_meminfo_stats(meminfo)" 4 | --- 5 | { 6 | "Active": 22188032.0, 7 | "AnonPages": 19955712.0, 8 | "Buffers": 4653056.0, 9 | "Cached": 53379072.0, 10 | "Dirty": 0.0, 11 | "Inactive": 52637696.0, 12 | "KReclaimable": 14364672.0, 13 | "KernelStack": 1949696.0, 14 | "Mapped": 30380032.0, 15 | "MemAvailable": 299098112.0, 16 | "MemFree": 248090624.0, 17 | "MemTotal": 374697984.0, 18 | "Mlocked": 0.0, 19 | "SReclaimable": 15269888.0, 20 | "SUnreclaim": 18952192.0, 21 | "Shmem": 11534336.0, 22 | "Slab": 34222080.0, 23 | "SwapCached": 0.0, 24 | "SwapFree": 0.0, 25 | "SwapTotal": 0.0, 26 | "Unevictable": 3145728.0, 27 | "Writeback": 0.0 28 | } 29 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__memory__test__get_memory_metrics_no_memavailable.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/memory.rs 3 | expression: memory_metrics_collector.get_memory_metrics().unwrap() 4 | --- 5 | [ 6 | { 7 | "name": "memory/memory/free", 8 | "value": { 9 | "Histogram": { 10 | "value": 248090624.0, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "memory/memory/used", 17 | "value": { 18 | "Histogram": { 19 | "value": 126607360.0, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "memory/memory/slab_recl", 26 | "value": { 27 | "Histogram": { 28 | "value": 15269888.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "memory/memory/slab_unrecl", 35 | "value": { 36 | "Histogram": { 37 | "value": 18952192.0, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | }, 42 | { 43 | "name": "memory/memory/buffered", 44 | "value": { 45 | "Histogram": { 46 | "value": 4653056.0, 47 | "timestamp": "[timestamp]" 48 | } 49 | } 50 | }, 51 | { 52 | "name": "memory/memory/cached", 53 | "value": { 54 | "Histogram": { 55 | "value": 53379072.0, 56 | "timestamp": "[timestamp]" 57 | } 58 | } 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__network_interfaces__test__eth0.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/network_interfaces.rs 3 | expression: "NetworkInterfaceMetricCollector::::parse_proc_net_dev_line(proc_net_dev_line).unwrap()" 4 | --- 5 | [ 6 | "eth0", 7 | [ 8 | 2707, 9 | 25, 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0, 16 | 2707, 17 | 25, 18 | 0, 19 | 0, 20 | 0, 21 | 0, 22 | 0, 23 | 0 24 | ] 25 | ] 26 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__network_interfaces__test__with_overflow_a_b_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/network_interfaces.rs 3 | expression: result_b.unwrap() 4 | --- 5 | [ 6 | { 7 | "name": "interface/eth0/packets_per_second/rx", 8 | "value": { 9 | "Histogram": { 10 | "value": 5.5, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "interface/eth0/errors_per_second/rx", 17 | "value": { 18 | "Histogram": { 19 | "value": 1.0, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "interface/eth0/dropped_per_second/rx", 26 | "value": { 27 | "Histogram": { 28 | "value": 1.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "interface/eth0/bytes_per_second/tx", 35 | "value": { 36 | "Histogram": { 37 | "value": 100.0, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | }, 42 | { 43 | "name": "interface/eth0/packets_per_second/tx", 44 | "value": { 45 | "Histogram": { 46 | "value": 2.5, 47 | "timestamp": "[timestamp]" 48 | } 49 | } 50 | }, 51 | { 52 | "name": "interface/eth0/errors_per_second/tx", 53 | "value": { 54 | "Histogram": { 55 | "value": 0.0, 56 | "timestamp": "[timestamp]" 57 | } 58 | } 59 | }, 60 | { 61 | "name": "interface/eth0/dropped_per_second/tx", 62 | "value": { 63 | "Histogram": { 64 | "value": 0.0, 65 | "timestamp": "[timestamp]" 66 | } 67 | } 68 | }, 69 | { 70 | "name": "interface/eth0/total_bytes/tx", 71 | "value": { 72 | "Counter": { 73 | "value": 1000.0, 74 | "timestamp": "[timestamp]" 75 | } 76 | } 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__network_interfaces__test__wlan1.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/network_interfaces.rs 3 | expression: "NetworkInterfaceMetricCollector::::parse_proc_net_dev_line(proc_net_dev_line).unwrap()" 4 | --- 5 | [ 6 | "wlan1", 7 | [ 8 | 2707, 9 | 25, 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 0, 16 | 2707, 17 | 25, 18 | 0, 19 | 0, 20 | 0, 21 | 0, 22 | 0, 23 | 0 24 | ] 25 | ] 26 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__processes__tests__process_metrics_auto_true.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/processes.rs 3 | expression: process_metric_readings_2 4 | --- 5 | [ 6 | { 7 | "name": "processes/memfaultd/cpu/percent/system", 8 | "value": { 9 | "Histogram": { 10 | "value": 0.05, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "processes/memfaultd/cpu/percent/user", 17 | "value": { 18 | "Histogram": { 19 | "value": 0.1, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "processes/memfaultd/num_threads", 26 | "value": { 27 | "Histogram": { 28 | "value": 19.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "processes/memfaultd/pagefaults/major", 35 | "value": { 36 | "Histogram": { 37 | "value": 0.0, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | }, 42 | { 43 | "name": "processes/memfaultd/pagefaults/minor", 44 | "value": { 45 | "Histogram": { 46 | "value": 0.0, 47 | "timestamp": "[timestamp]" 48 | } 49 | } 50 | }, 51 | { 52 | "name": "processes/memfaultd/rss_bytes", 53 | "value": { 54 | "Histogram": { 55 | "value": 18010112.0, 56 | "timestamp": "[timestamp]" 57 | } 58 | } 59 | }, 60 | { 61 | "name": "processes/memfaultd/vm_bytes", 62 | "value": { 63 | "Histogram": { 64 | "value": 1411293184.0, 65 | "timestamp": "[timestamp]" 66 | } 67 | } 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__processes__tests__simple_cpu_delta_metrics.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/processes.rs 3 | expression: process_metric_readings.unwrap() 4 | --- 5 | [ 6 | { 7 | "name": "processes/memfaultd/rss_bytes", 8 | "value": { 9 | "Histogram": { 10 | "value": 18010112.0, 11 | "timestamp": "[timestamp]" 12 | } 13 | } 14 | }, 15 | { 16 | "name": "processes/memfaultd/vm_bytes", 17 | "value": { 18 | "Histogram": { 19 | "value": 1411293184.0, 20 | "timestamp": "[timestamp]" 21 | } 22 | } 23 | }, 24 | { 25 | "name": "processes/memfaultd/num_threads", 26 | "value": { 27 | "Histogram": { 28 | "value": 19.0, 29 | "timestamp": "[timestamp]" 30 | } 31 | } 32 | }, 33 | { 34 | "name": "processes/memfaultd/cpu/percent/system", 35 | "value": { 36 | "Histogram": { 37 | "value": 0.05, 38 | "timestamp": "[timestamp]" 39 | } 40 | } 41 | }, 42 | { 43 | "name": "processes/memfaultd/cpu/percent/user", 44 | "value": { 45 | "Histogram": { 46 | "value": 0.1, 47 | "timestamp": "[timestamp]" 48 | } 49 | } 50 | }, 51 | { 52 | "name": "processes/memfaultd/pagefaults/minor", 53 | "value": { 54 | "Histogram": { 55 | "value": 50.0, 56 | "timestamp": "[timestamp]" 57 | } 58 | } 59 | }, 60 | { 61 | "name": "processes/memfaultd/pagefaults/major", 62 | "value": { 63 | "Histogram": { 64 | "value": 10.0, 65 | "timestamp": "[timestamp]" 66 | } 67 | } 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /memfaultd/src/metrics/system_metrics/snapshots/memfaultd__metrics__system_metrics__thermal__tests__read_thermal_zone_temp.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/metrics/system_metrics/thermal.rs 3 | expression: result 4 | --- 5 | { 6 | "name": "thermal/cpu-temp/temp", 7 | "value": { 8 | "Histogram": { 9 | "value": 50.0, 10 | "timestamp": "[timestamp]" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /memfaultd/src/network/snapshots/memfaultd__network__requests__test__device_config.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/network/requests.rs 3 | expression: response 4 | --- 5 | { 6 | "data": { 7 | "config": { 8 | "memfault": { 9 | "sampling": { 10 | "debugging.resolution": "normal", 11 | "logging.resolution": "high", 12 | "monitoring.resolution": "low" 13 | }, 14 | "data_upload_start_date": "1991-03-25T00:00:00+00:00" 15 | } 16 | }, 17 | "revision": 123, 18 | "completed": 100 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /memfaultd/src/network/snapshots/memfaultd__network__requests__test__device_config_missing_upload_start.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/network/requests.rs 3 | expression: response 4 | --- 5 | { 6 | "data": { 7 | "config": { 8 | "memfault": { 9 | "sampling": { 10 | "debugging.resolution": "normal", 11 | "logging.resolution": "high", 12 | "monitoring.resolution": "low" 13 | }, 14 | "data_upload_start_date": null 15 | } 16 | }, 17 | "revision": 123, 18 | "completed": 100 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /memfaultd/src/network/snapshots/memfaultd__network__requests__test__prepare_upload_serialization.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: memfaultd/src/network/requests.rs 3 | expression: prepare_request 4 | snapshot_kind: text 5 | --- 6 | { 7 | "content_encoding": null, 8 | "size": 123, 9 | "device": { 10 | "device_serial": "device_id", 11 | "hardware_version": "hardware_version", 12 | "software_version": "software_version", 13 | "software_type": "software_type" 14 | }, 15 | "kind": "MAR" 16 | } 17 | -------------------------------------------------------------------------------- /memfaultd/src/service_manager/default.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use nix::sys::signal::Signal::SIGHUP; 5 | 6 | use crate::util::pid_file::send_signal_to_pid; 7 | 8 | use super::MemfaultdServiceManager; 9 | 10 | pub struct DefaultServiceManager; 11 | 12 | impl MemfaultdServiceManager for DefaultServiceManager { 13 | fn restart_memfaultd_if_running(&self) -> eyre::Result<()> { 14 | send_signal_to_pid(SIGHUP) 15 | } 16 | 17 | fn service_manager_status(&self) -> eyre::Result { 18 | Ok(super::ServiceManagerStatus::Unknown) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /memfaultd/src/service_manager/systemd.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::ffi::{CStr, CString}; 5 | 6 | use crate::service_manager::{MemfaultdServiceManager, ServiceManagerStatus}; 7 | use memfaultc_sys::systemd::{ 8 | memfaultd_get_systemd_bus_state, memfaultd_restart_systemd_service_if_running, 9 | }; 10 | 11 | /// Systemd service manager 12 | /// 13 | /// This service manager uses the systemd D-Bus API to manage services. 14 | pub struct SystemdServiceManager; 15 | 16 | impl MemfaultdServiceManager for SystemdServiceManager { 17 | fn restart_memfaultd_if_running(&self) -> eyre::Result<()> { 18 | let service_cstring = CString::new("memfaultd.service")?; 19 | let restart_result = 20 | unsafe { memfaultd_restart_systemd_service_if_running(service_cstring.as_ptr()) }; 21 | 22 | if restart_result { 23 | Ok(()) 24 | } else { 25 | Err(eyre::eyre!("Failed to restart memfaultd service")) 26 | } 27 | } 28 | 29 | fn service_manager_status(&self) -> eyre::Result { 30 | let status_ptr = unsafe { memfaultd_get_systemd_bus_state() }; 31 | if status_ptr.is_null() { 32 | return Err(eyre::eyre!("Failed to get systemd service bus state")); 33 | } 34 | 35 | let status_str = unsafe { CStr::from_ptr(status_ptr).to_str()? }; 36 | let status = ServiceManagerStatus::try_from(status_str)?; 37 | 38 | unsafe { libc::free(status_ptr as *mut libc::c_void) }; 39 | 40 | Ok(status) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /memfaultd/src/swupdate/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod config; 5 | 6 | pub use config::generate_swupdate_config; 7 | -------------------------------------------------------------------------------- /memfaultd/src/test_utils/test_connection_checker.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::{cell::RefCell, net::IpAddr, time::Duration}; 5 | 6 | use eyre::{eyre, Result}; 7 | 8 | use crate::util::can_connect::CanConnect; 9 | 10 | #[derive(Debug, Clone, Copy)] 11 | pub struct TestConnectionChecker {} 12 | 13 | thread_local! { 14 | static CONNECTED: RefCell = RefCell::new(true); 15 | } 16 | 17 | impl TestConnectionChecker { 18 | pub fn connect() { 19 | CONNECTED.with(|c| *c.borrow_mut() = true); 20 | } 21 | 22 | pub fn disconnect() { 23 | CONNECTED.with(|c| *c.borrow_mut() = false); 24 | } 25 | } 26 | 27 | impl CanConnect for TestConnectionChecker { 28 | fn new(_timeout: Duration) -> Self { 29 | Self {} 30 | } 31 | 32 | fn can_connect(&self, _ip: &IpAddr, _port: u16) -> Result<()> { 33 | let mut connected_status = true; 34 | CONNECTED.with(|c| connected_status = *c.borrow()); 35 | if connected_status { 36 | Ok(()) 37 | } else { 38 | Err(eyre!("MockPinger is set to disconnected")) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /memfaultd/src/util/die.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | //! In loving memory of the practical extraction and report language. 5 | use std::error::Error; 6 | 7 | use log::error; 8 | 9 | /// Prints the error message to the error log, and then panics. 10 | pub fn die(e: E) -> ! { 11 | error!("Irrecoverable error: {:#}", e); 12 | panic!("Irrecoverable error: {:#}", e) 13 | } 14 | 15 | pub trait UnwrapOrDie { 16 | fn unwrap_or_die(self) -> T; 17 | } 18 | 19 | impl UnwrapOrDie for Result { 20 | fn unwrap_or_die(self) -> T { 21 | match self { 22 | Ok(v) => v, 23 | Err(e) => die(e), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /memfaultd/src/util/ipc.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use eyre::Result; 5 | use nix::sys::signal::Signal::{SIGUSR1, SIGUSR2}; 6 | 7 | use super::pid_file::send_signal_to_pid; 8 | 9 | pub fn send_flush_signal(skip_serialization: bool) -> Result<()> { 10 | send_signal_to_pid(if skip_serialization { SIGUSR2 } else { SIGUSR1 }) 11 | } 12 | -------------------------------------------------------------------------------- /memfaultd/src/util/math.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | /// Rounds the given value up to the nearest multiple of the given alignment. 5 | /// 6 | /// For values <= 1, the value is returned unchanged. 7 | pub fn align_up(value: usize, alignment: usize) -> usize { 8 | if alignment <= 1 { 9 | return value; 10 | } 11 | ((value) + (alignment - 1)) & !(alignment - 1) 12 | } 13 | 14 | /// We need to account for potential rollovers in the 15 | /// /proc/net/dev counters, handled by this function 16 | pub fn counter_delta_with_overflow(current: u64, previous: u64) -> u64 { 17 | // The only time a counter's value would be less 18 | // that its previous value is if it rolled over 19 | // due to overflow - drop these readings that overlap 20 | // with an overflow 21 | if current < previous { 22 | // Need to detect if the counter rolled over at u32::MAX or u64::MAX 23 | current 24 | + ((if previous > u32::MAX as u64 { 25 | u64::MAX 26 | } else { 27 | u32::MAX as u64 28 | }) - previous) 29 | } else { 30 | current - previous 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /memfaultd/src/util/mem.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::mem::size_of; 5 | use std::slice::{from_raw_parts, from_raw_parts_mut}; 6 | 7 | pub trait AsBytes { 8 | /// Returns a slice of bytes representing the raw memory of the object. 9 | /// # Safety 10 | /// It is on the caller to ensure the interpretation of the bytes is correct. 11 | unsafe fn as_bytes(&self) -> &[u8]; 12 | 13 | /// Returns a mutable slice of bytes representing the raw memory of the object. 14 | /// # Safety 15 | /// The type must not contain any references, pointers or types that require 16 | /// validating invariants. 17 | unsafe fn as_mut_bytes(&mut self) -> &mut [u8]; 18 | } 19 | 20 | impl AsBytes for T { 21 | unsafe fn as_bytes(&self) -> &[u8] { 22 | from_raw_parts((self as *const T) as *const u8, size_of::()) 23 | } 24 | 25 | unsafe fn as_mut_bytes(&mut self) -> &mut [u8] { 26 | from_raw_parts_mut((self as *mut T) as *mut u8, size_of::()) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /memfaultd/src/util/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | mod disk_backed; 5 | pub use disk_backed::*; 6 | mod die; 7 | pub mod disk_size; 8 | pub mod patterns; 9 | pub use die::*; 10 | pub mod can_connect; 11 | pub mod circular_queue; 12 | pub mod etc_os_release; 13 | pub mod fs; 14 | pub mod io; 15 | pub mod ipc; 16 | pub mod math; 17 | pub mod mem; 18 | pub mod output_arg; 19 | pub mod path; 20 | pub mod persistent_rate_limiter; 21 | pub mod pid_file; 22 | pub mod rate_limiter; 23 | pub mod serialization; 24 | pub mod string; 25 | pub mod system; 26 | pub mod task; 27 | #[cfg(feature = "logging")] 28 | pub mod tcp_server; 29 | pub mod time_measure; 30 | pub mod wildcard_pattern; 31 | pub mod zip; 32 | pub mod zip_dir; 33 | -------------------------------------------------------------------------------- /memfaultd/src/util/output_arg.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::{ 5 | fs::File, 6 | io::{stdout, Write}, 7 | path::PathBuf, 8 | }; 9 | 10 | use argh::FromArgValue; 11 | use eyre::{Context, Result}; 12 | 13 | /// An Argh argument that can be either a `PathBuf` or a reference to `stdout` (`-`). 14 | pub enum OutputArg { 15 | Stdout, 16 | File(PathBuf), 17 | } 18 | 19 | impl FromArgValue for OutputArg { 20 | fn from_arg_value(value: &str) -> Result { 21 | if value == "-" { 22 | Ok(OutputArg::Stdout) 23 | } else { 24 | Ok(OutputArg::File(value.into())) 25 | } 26 | } 27 | } 28 | 29 | impl OutputArg { 30 | /// Open the output stream designated by the user. 31 | pub fn get_output_stream(&self) -> Result> { 32 | let stream: Box = 33 | match self { 34 | OutputArg::Stdout => Box::new(stdout()), 35 | OutputArg::File(path) => Box::new(File::create(path).wrap_err_with(|| { 36 | format!("Error opening destination file {}", path.display()) 37 | })?), 38 | }; 39 | 40 | Ok(stream) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /memfaultd/src/util/path.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use eyre::{eyre, Error, Result}; 5 | use std::path::Path; 6 | use std::{ffi::OsStr, path::PathBuf}; 7 | 8 | use serde::{Deserialize, Serialize}; 9 | 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | #[serde(try_from = "PathBuf")] 12 | /// A path that must be absolute. Use `AbsolutePath::try_from` to construct. 13 | pub struct AbsolutePath(PathBuf); 14 | 15 | impl TryFrom for AbsolutePath { 16 | type Error = Error; 17 | 18 | fn try_from(path: PathBuf) -> Result { 19 | if path.is_absolute() { 20 | Ok(Self(path)) 21 | } else { 22 | Err(eyre!("Path must be absolute: {:?}", path)) 23 | } 24 | } 25 | } 26 | impl From for PathBuf { 27 | fn from(p: AbsolutePath) -> PathBuf { 28 | p.0 29 | } 30 | } 31 | impl PartialEq for PathBuf { 32 | fn eq(&self, other: &AbsolutePath) -> bool { 33 | *self == *other.0 34 | } 35 | } 36 | 37 | impl std::ops::Deref for AbsolutePath { 38 | type Target = Path; 39 | #[inline] 40 | fn deref(&self) -> &Path { 41 | self.0.as_path() 42 | } 43 | } 44 | 45 | /// Splits the filename at the first dot. 46 | /// This is similar to the nighly-only std::path::Path::file_prefix. 47 | #[allow(dead_code)] 48 | pub fn file_prefix(path: &Path) -> Option<&OsStr> { 49 | let file_name = path.file_name()?; 50 | file_name.to_str()?.split('.').next().map(OsStr::new) 51 | } 52 | 53 | #[cfg(test)] 54 | mod tests { 55 | use rstest::rstest; 56 | 57 | use super::*; 58 | 59 | #[rstest] 60 | #[case("/test", "test")] 61 | #[case("/test.log", "test")] 62 | #[case("/test.log.zlib", "test")] 63 | fn test_file_prefix(#[case] path: &str, #[case] expected: &str) { 64 | assert_eq!(file_prefix(Path::new(path)), Some(OsStr::new(expected))); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/datetime_to_rfc3339.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use chrono::{DateTime, Utc}; 5 | use serde::{Deserialize, Deserializer, Serializer}; 6 | 7 | pub fn serialize(time: &DateTime, serializer: S) -> Result 8 | where 9 | S: Serializer, 10 | { 11 | let datetime_str = time.to_rfc3339(); 12 | serializer.serialize_str(&datetime_str) 13 | } 14 | 15 | pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 16 | where 17 | D: Deserializer<'de>, 18 | { 19 | let datetime_str = String::deserialize(deserializer)?; 20 | let datetime = DateTime::parse_from_rfc3339(&datetime_str) 21 | .map_err(|e| serde::de::Error::custom(format!("invalid timestamp: {}", e)))?; 22 | 23 | Ok(datetime.with_timezone(&Utc)) 24 | } 25 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/float_to_datetime.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use chrono::{DateTime, Utc}; 5 | use serde::{Deserialize, Deserializer, Serializer}; 6 | 7 | pub fn serialize(time: &DateTime, serializer: S) -> Result 8 | where 9 | S: Serializer, 10 | { 11 | serializer.serialize_f64( 12 | time.timestamp() as f64 + (time.timestamp_subsec_micros() as f64 / 1_000_000.0), 13 | ) 14 | } 15 | 16 | pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 17 | where 18 | D: Deserializer<'de>, 19 | { 20 | let secs = f64::deserialize(deserializer)?; 21 | 22 | // Collectd only sends milli-seconds. We round the float to the nearest ms 23 | // to avoid precision error. 24 | let ms = ((secs.rem_euclid(1.0)) * 1e3).round() as u32; 25 | 26 | match DateTime::from_timestamp(secs.floor() as i64, ms * 1_000_000) { 27 | Some(datetime) => Ok(datetime), 28 | None => Err(serde::de::Error::custom("invalid timestamp")), 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/float_to_duration.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use chrono::Duration; 5 | use serde::{Deserialize, Deserializer, Serializer}; 6 | 7 | pub fn serialize(duration: &Duration, serializer: S) -> Result 8 | where 9 | S: Serializer, 10 | { 11 | serializer 12 | .serialize_f64(duration.num_seconds() as f64 + duration.num_milliseconds() as f64 / 1000.0) 13 | } 14 | 15 | pub fn deserialize<'de, D>(deserializer: D) -> Result 16 | where 17 | D: Deserializer<'de>, 18 | { 19 | let d = f64::deserialize(deserializer)?; 20 | let seconds = d.trunc() as i64; 21 | let ms = (d.rem_euclid(1.0) * 1000.0) as i64; 22 | Ok(Duration::seconds(seconds) + Duration::milliseconds(ms)) 23 | } 24 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/kib_to_usize.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 5 | 6 | pub fn serialize(size: &usize, serializer: S) -> Result 7 | where 8 | S: Serializer, 9 | { 10 | if size % 1024 != 0 { 11 | return Err(serde::ser::Error::custom( 12 | "Cannot serialize non-multiple of 1024 to kib.", 13 | )); 14 | } 15 | (size / 1024).serialize(serializer) 16 | } 17 | 18 | pub fn deserialize<'de, D>(deserializer: D) -> Result 19 | where 20 | D: Deserializer<'de>, 21 | { 22 | let size = usize::deserialize(deserializer)?; 23 | Ok(size * 1024) 24 | } 25 | 26 | #[cfg(test)] 27 | mod tests { 28 | 29 | #[test] 30 | fn serialize_error() { 31 | let mut serializer = serde_json::Serializer::new(std::io::stdout()); 32 | let r = super::serialize(&1025, &mut serializer); 33 | assert!(r.is_err()); 34 | } 35 | 36 | #[test] 37 | fn serialize_multiple_of_1024() { 38 | let mut buf = Vec::new(); 39 | let mut serializer = serde_json::Serializer::new(&mut buf); 40 | let r = super::serialize(&43008, &mut serializer); 41 | assert!(r.is_ok()); 42 | 43 | assert_eq!(&buf, b"42"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/milliseconds_to_duration.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use serde::{Deserialize, Deserializer, Serializer}; 5 | 6 | use std::time::Duration; 7 | 8 | pub fn serialize(duration: &Duration, serializer: S) -> Result 9 | where 10 | S: Serializer, 11 | { 12 | serializer.serialize_u128(duration.as_millis()) 13 | } 14 | 15 | pub fn deserialize<'de, D>(deserializer: D) -> Result 16 | where 17 | D: Deserializer<'de>, 18 | { 19 | let secs = u64::deserialize(deserializer)?; 20 | Ok(Duration::from_millis(secs)) 21 | } 22 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | pub mod datetime_to_rfc3339; 5 | pub mod float_to_datetime; 6 | pub mod float_to_duration; 7 | pub mod kib_to_usize; 8 | pub mod milliseconds_to_duration; 9 | pub mod number_to_compression; 10 | pub mod optional_datetime_to_rfc3339; 11 | pub mod optional_milliseconds_to_duration; 12 | pub mod seconds_to_duration; 13 | pub mod sorted_map; 14 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/number_to_compression.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use flate2::Compression; 5 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 6 | 7 | pub fn serialize(compression: &Compression, serializer: S) -> Result 8 | where 9 | S: Serializer, 10 | { 11 | (compression.level()).serialize(serializer) 12 | } 13 | 14 | pub fn deserialize<'de, D>(deserializer: D) -> Result 15 | where 16 | D: Deserializer<'de>, 17 | { 18 | let level = u32::deserialize(deserializer)?; 19 | match level { 20 | 0..=9 => Ok(Compression::new(level)), 21 | _ => Err(serde::de::Error::custom( 22 | "Compression level must be between 0 and 9.", 23 | )), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/optional_datetime_to_rfc3339.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use chrono::{DateTime, Utc}; 5 | use serde::{Deserialize, Deserializer, Serializer}; 6 | 7 | pub fn serialize(time: &Option>, serializer: S) -> Result 8 | where 9 | S: Serializer, 10 | { 11 | let datetime_str = time.map(|t| t.to_rfc3339()); 12 | match datetime_str { 13 | Some(datetime_str) => serializer.serialize_some(&datetime_str), 14 | None => serializer.serialize_none(), 15 | } 16 | } 17 | 18 | pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> 19 | where 20 | D: Deserializer<'de>, 21 | { 22 | let datetime_str = ::deserialize(deserializer); 23 | match datetime_str { 24 | Ok(datetime_str) => { 25 | let datetime = DateTime::parse_from_rfc3339(&datetime_str) 26 | .ok() 27 | .map(|datetime| datetime.with_timezone(&Utc)); 28 | Ok(datetime) 29 | } 30 | Err(_) => Ok(None), 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/optional_milliseconds_to_duration.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use serde::{Deserialize, Deserializer, Serializer}; 5 | 6 | use std::time::Duration; 7 | 8 | pub fn serialize(duration: &Option, serializer: S) -> Result 9 | where 10 | S: Serializer, 11 | { 12 | if let Some(duration) = duration { 13 | serializer.serialize_u128(duration.as_millis()) 14 | } else { 15 | serializer.serialize_none() 16 | } 17 | } 18 | 19 | pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 20 | where 21 | D: Deserializer<'de>, 22 | { 23 | if let Ok(secs) = u64::deserialize(deserializer) { 24 | Ok(Some(Duration::from_millis(secs))) 25 | } else { 26 | Ok(None) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/seconds_to_duration.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use serde::{Deserialize, Deserializer, Serializer}; 5 | 6 | use std::time::Duration; 7 | 8 | pub fn serialize(duration: &Duration, serializer: S) -> Result 9 | where 10 | S: Serializer, 11 | { 12 | serializer.serialize_u64(duration.as_secs()) 13 | } 14 | 15 | pub fn deserialize<'de, D>(deserializer: D) -> Result 16 | where 17 | D: Deserializer<'de>, 18 | { 19 | let secs = u64::deserialize(deserializer)?; 20 | Ok(Duration::from_secs(secs)) 21 | } 22 | -------------------------------------------------------------------------------- /memfaultd/src/util/serialization/sorted_map.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::collections::{BTreeMap, HashMap}; 5 | 6 | use serde::{Serialize, Serializer}; 7 | 8 | pub fn sorted_map( 9 | value: &HashMap, 10 | serializer: S, 11 | ) -> Result { 12 | let mut items: Vec<(_, _)> = value.iter().collect(); 13 | items.sort_by(|a, b| a.0.cmp(b.0)); 14 | BTreeMap::from_iter(items).serialize(serializer) 15 | } 16 | -------------------------------------------------------------------------------- /memfaultd/src/util/time_measure.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::time::{Duration, Instant}; 5 | 6 | /// A trait for measuring time. 7 | /// 8 | /// This is mostly a way to mock std::time::Instant for testing. 9 | pub trait TimeMeasure { 10 | fn now() -> Self; 11 | fn elapsed(&self) -> Duration; 12 | fn since(&self, other: &Self) -> Duration; 13 | } 14 | 15 | impl TimeMeasure for Instant { 16 | fn now() -> Self { 17 | Instant::now() 18 | } 19 | 20 | fn elapsed(&self) -> Duration { 21 | Self::now().since(self) 22 | } 23 | 24 | fn since(&self, other: &Self) -> Duration { 25 | Instant::duration_since(self, *other) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /memfaultd/src/util/zip_dir.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Memfault, Inc. 3 | // See License.txt for details 4 | use std::{ 5 | fs::{DirEntry, File}, 6 | io::{Read, Seek, Write}, 7 | path::Path, 8 | }; 9 | use zip::{write::SimpleFileOptions, ZipWriter}; 10 | 11 | use eyre::{ContextCompat, Result}; 12 | 13 | /// Compress 14 | pub fn zip_dir( 15 | it: &mut dyn Iterator, 16 | prefix: &Path, 17 | writer: T, 18 | method: zip::CompressionMethod, 19 | ) -> Result<()> 20 | where 21 | T: Write + Seek, 22 | { 23 | let mut zip = ZipWriter::new(writer); 24 | let options = SimpleFileOptions::default() 25 | .compression_method(method) 26 | .unix_permissions(0o755); 27 | 28 | let prefix = Path::new(prefix); 29 | let mut buffer = Vec::new(); 30 | for entry in it { 31 | let path = entry.path(); 32 | let name = path.strip_prefix(prefix)?; 33 | let path_as_string = name 34 | .to_str() 35 | .map(str::to_owned) 36 | .wrap_err_with(|| format!("{name:?} Is a Non UTF-8 Path"))?; 37 | 38 | // Write file or directory explicitly 39 | // Some unzip tools unzip files with directory paths correctly, some do not! 40 | if path.is_file() { 41 | zip.start_file(path_as_string, options)?; 42 | let mut f = File::open(path)?; 43 | 44 | f.read_to_end(&mut buffer)?; 45 | zip.write_all(&buffer)?; 46 | buffer.clear(); 47 | } else if !name.as_os_str().is_empty() { 48 | // Only if not root! Avoids path spec / warning 49 | // and mapname conversion failed error on unzip 50 | zip.add_directory(path_as_string, options)?; 51 | } 52 | } 53 | zip.finish()?; 54 | Ok(()) 55 | } 56 | --------------------------------------------------------------------------------