diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 4c5a3355..caeb5688 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -74,7 +74,11 @@ create_statistical_detector, ) from scos_actions.signals import measurement_action_completed, trigger_api_restart -from scos_actions.utils import convert_datetime_to_millisecond_iso_format, get_days_up +from scos_actions.utils import ( + convert_datetime_to_millisecond_iso_format, + get_days_up, + get_disk_usage, +) env = Env() logger = logging.getLogger(__name__) @@ -785,6 +789,11 @@ def capture_diagnostics( cpu_diag["ssd_smart_data"] = ntia_diagnostics.SsdSmartData(**smart_data) except: logger.warning("Failed to get SSD SMART data") + try: # Disk usage + disk_usage = get_disk_usage() + cpu_diag["disk_usage"] = disk_usage + except: + logger.warning("Failed to get disk usage") # Get software versions software_diag = { diff --git a/scos_actions/actions/acquire_stepped_freq_tdomain_iq.py b/scos_actions/actions/acquire_stepped_freq_tdomain_iq.py index e8cc1d5f..bfb06d55 100644 --- a/scos_actions/actions/acquire_stepped_freq_tdomain_iq.py +++ b/scos_actions/actions/acquire_stepped_freq_tdomain_iq.py @@ -112,7 +112,6 @@ def __call__(self, sensor: Sensor, schedule_entry: dict, task_id: int): sigan_settings = self.get_sigan_settings(measurement_result) capture_segment = CaptureSegment( sample_start=0, - global_index=saved_samples, frequency=measurement_params[FREQUENCY], datetime=measurement_result["capture_time"], duration=duration_ms, diff --git a/scos_actions/hardware/utils.py b/scos_actions/hardware/utils.py index 49642da7..8a286e6d 100644 --- a/scos_actions/hardware/utils.py +++ b/scos_actions/hardware/utils.py @@ -1,6 +1,6 @@ import logging import subprocess -from typing import Dict +from typing import Dict, Tuple, Union import psutil from its_preselector.web_relay import WebRelay @@ -66,7 +66,7 @@ def get_current_cpu_temperature(fahrenheit: bool = False) -> float: raise e -def get_disk_smart_data(disk: str) -> dict: +def get_disk_smart_data(disk: str) -> Union[dict, str]: """ Get selected SMART data for the chosen disk. @@ -81,7 +81,8 @@ def get_disk_smart_data(disk: str) -> dict: https://nvmexpress.org/wp-content/uploads/NVM-Express-1_4-2019.06.10-Ratified.pdf :param disk: The desired disk, e.g., ``/dev/nvme0n1``. - :return: A dictionary containing the retrieved data from the SMART report. + :return: A dictionary containing the retrieved data from the SMART report, or + the string "Unavailable" if ``smartctl`` fails to run. """ try: report = subprocess.check_output(["smartctl", "-a", disk]).decode("utf-8") diff --git a/scos_actions/metadata/sigmf_builder.py b/scos_actions/metadata/sigmf_builder.py index 2a838d82..2ed489e7 100644 --- a/scos_actions/metadata/sigmf_builder.py +++ b/scos_actions/metadata/sigmf_builder.py @@ -27,7 +27,7 @@ }, { "name": "ntia-diagnostics", - "version": "2.0.0", + "version": "2.2.0", "optional": True, }, { @@ -266,7 +266,7 @@ def set_collection(self, collection: str) -> None: """ self.sigmf_md.set_global_field("core:collection", collection) - ### ntia-algorithm v2.0.0 ### + ### ntia-algorithm v2.0.1 ### def set_data_products(self, data_products: List[Graph]) -> None: """ @@ -311,7 +311,7 @@ def set_classification(self, classification: str) -> None: """ self.sigmf_md.set_global_field("ntia-core:classification", classification) - ### ntia-diagnostics v1.0.0 ### + ### ntia-diagnostics v2.2.0 ### def set_diagnostics(self, diagnostics: Diagnostics) -> None: """ diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index def0cbd5..a0ef7c8d 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -129,16 +129,20 @@ class Computer(msgspec.Struct, **SIGMF_OBJECT_KWARGS): :param cpu_mean_clock: Mean sampled clock speed, in MHz. :param cpu_uptime: Number of days since the computer started. :param action_cpu_usage: CPU utilization during action execution, as a percentage. + :param action_runtime: Total action execution time, in seconds. :param system_load_5m: Number of processes in a runnable state over the previous 5 minutes as a percentage of the number of CPUs. :param memory_usage: Average percent of memory used during action execution. :param cpu_overheating: Whether the CPU is overheating. :param cpu_temp: CPU temperature, in degrees Celsius. - :param scos_start: The time at which the SCOS API container started. Must be + :param software_start: The time at which the sensor software started. Must be an ISO 8601 formatted string. - :param scos_uptime: Number of days since the SCOS API container started. + :param software_uptime: Number of days since the sensor software started. :param ssd_smart_data: Information provided by the drive Self-Monitoring, Analysis, and Reporting Technology. + :param ntp_active: True if NTP service is active on the computer. + :param ntp_sync: True if the system clock is synchronized with NTP. + :param disk_usage: Total computer disk usage, as a percentage. """ cpu_min_clock: Optional[float] = None @@ -154,6 +158,9 @@ class Computer(msgspec.Struct, **SIGMF_OBJECT_KWARGS): software_start: Optional[str] = None software_uptime: Optional[float] = None ssd_smart_data: Optional[SsdSmartData] = None + ntp_active: Optional[bool] = None + ntp_sync: Optional[bool] = None + disk_usage: Optional[float] = None class ScosPlugin(msgspec.Struct, **SIGMF_OBJECT_KWARGS): diff --git a/scos_actions/utils.py b/scos_actions/utils.py index e70a4324..182474ce 100644 --- a/scos_actions/utils.py +++ b/scos_actions/utils.py @@ -1,5 +1,6 @@ import json import logging +import shutil from datetime import datetime from pathlib import Path @@ -124,3 +125,11 @@ def get_days_up(start_time): days = elapsed.days fractional_day = elapsed.seconds / (60 * 60 * 24) return round(days + fractional_day, 4) + + +def get_disk_usage() -> float: + """Return the total disk usage as a percentage.""" + usage = shutil.disk_usage("/") + percent_used = round(100 * usage.used / usage.total) + logger.debug(f"{percent_used} disk used") + return round(percent_used, 2)