| #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_ |
| #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_ |
| |
| #include <chrono> // NOLINT |
| #include <cstddef> |
| #include <cstdint> |
| #include <memory> |
| #include <optional> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/container/btree_set.h" |
| #include "absl/log/log.h" |
| #include "absl/status/status.h" |
| #include "absl/synchronization/mutex.h" |
| #include "absl/time/time.h" |
| #include "boost/circular_buffer.hpp" //NOLINT: boost is commonly used in BMC |
| #include "entity_common_config.pb.h" |
| #include "hal_common_config.pb.h" |
| #include "reading_transform_config.pb.h" |
| #include "tlbmc/configs/subscription_config.h" |
| #include "resource.pb.h" |
| #include "sensor.pb.h" |
| #include "tlbmc/sensors/sensor.h" |
| |
| namespace milotic_tlbmc { |
| |
| // A sensor which is actively polled to read its value from the hardware, sysfs, |
| // etc. This is typically done by calls to RefreshOnceAsync(). |
| // This sensor stores latest readings and collects metrics. |
| // Any implementation of this interface must be thread-safe regarding the listed |
| // functions. |
| class PollingBaseSensor : public Sensor { |
| public: |
| virtual ~PollingBaseSensor() = default; |
| |
| // Returns the latest sensor reading. |
| std::shared_ptr<const SensorValue> GetSensorData() const override |
| ABSL_LOCKS_EXCLUDED(sensor_data_mutex_, override_mutex_) { |
| { |
| absl::MutexLock lock(override_mutex_); |
| if (override_value_.has_value()) { |
| return std::make_shared<const SensorValue>(*override_value_); |
| } |
| } |
| absl::MutexLock lock(sensor_data_mutex_); |
| return sensor_data_.empty() ? nullptr : sensor_data_.back(); |
| } |
| |
| std::vector<std::shared_ptr<const SensorValue>> GetSensorDataHistory() |
| const override ABSL_LOCKS_EXCLUDED(sensor_data_mutex_) { |
| absl::MutexLock lock(sensor_data_mutex_); |
| return {sensor_data_.begin(), sensor_data_.end()}; |
| } |
| |
| std::vector<std::shared_ptr<const SensorValue>> GetSensorDataHistorySince( |
| absl::Time start_time) const override |
| ABSL_LOCKS_EXCLUDED(sensor_data_mutex_); |
| |
| SensorMetrics GetSensorMetrics() const override; |
| |
| // Subscribes to the sensor data. |
| // TODO(ronvered): Consider for removal, since it's used in tests only. |
| absl::Status Subscribe(const SubscriptionParams* subscription_params); |
| // Deletes an existing subscription. |
| absl::Status Unsubscribe(const SubscriptionParams* subscription_params); |
| |
| // Resize the buffer for the sensor. |
| void ResizeBuffer(size_t buffer_size) override; |
| // Resets the metrics for the sensor. This is used when the sensor is |
| // configured with a different sampling interval. |
| void ResetMetrics() override; |
| |
| protected: |
| PollingBaseSensor(SensorAttributesStatic&& sensor_attributes_static, |
| const ThresholdConfigs& threshold_configs, |
| std::optional<NotificationCb> notification_cb) |
| : Sensor(std::move(sensor_attributes_static), threshold_configs, |
| notification_cb), |
| sensor_data_(static_cast<size_t>( |
| sensor_attributes_static_.entity_common_config().queue_size())) {} |
| PollingBaseSensor() : sensor_data_(1) { |
| DLOG(INFO) << "Sensor created with default queue size of " |
| << sensor_data_.capacity(); |
| } |
| |
| // Buffers the sensor data and notifies the subscribers if the batch size |
| // reaches the threshold. |
| void StoreSensorData(const std::shared_ptr<const SensorValue>& sensor_data) |
| ABSL_LOCKS_EXCLUDED(sensor_data_mutex_, |
| sensor_attributes_dynamic_mutex_) override; |
| |
| // Given the latency of the most recent hardware polling latency, updates the |
| // metrics. |
| void UpdateHardwarePollingMetrics(std::chrono::steady_clock::duration latency) |
| ABSL_LOCKS_EXCLUDED(sensor_metrics_mutex_); |
| |
| // Given the timestamp of the most recent software polling read start |
| // interval, updates the metrics. |
| void UpdateSoftwarePollingStartMetrics( |
| std::chrono::steady_clock::duration interval) |
| ABSL_LOCKS_EXCLUDED(sensor_metrics_mutex_); |
| |
| // Given the timestamp of the most recent software polling read end interval, |
| // updates the metrics. |
| void UpdateSoftwarePollingEndMetrics( |
| std::chrono::steady_clock::duration interval) |
| ABSL_LOCKS_EXCLUDED(sensor_metrics_mutex_); |
| |
| void SetLastRefreshStartTime(std::chrono::steady_clock::time_point time) { |
| // NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor. |
| absl::MutexLock lock(sensor_metrics_mutex_); |
| last_refresh_start_time_ = time; |
| } |
| |
| std::chrono::steady_clock::time_point GetLastRefreshStartTime() const { |
| // NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor. |
| absl::MutexLock lock(sensor_metrics_mutex_); |
| return last_refresh_start_time_; |
| } |
| |
| void SetLastRefreshEndTime(std::chrono::steady_clock::time_point time) { |
| // NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor. |
| absl::MutexLock lock(sensor_metrics_mutex_); |
| last_refresh_end_time_ = time; |
| } |
| |
| std::chrono::steady_clock::time_point GetLastRefreshEndTime() const { |
| // NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor. |
| absl::MutexLock lock(sensor_metrics_mutex_); |
| return last_refresh_end_time_; |
| } |
| |
| mutable absl::Mutex sensor_data_mutex_; |
| // Front() returns the oldest data. |
| boost::circular_buffer<std::shared_ptr<const SensorValue>> sensor_data_ |
| ABSL_GUARDED_BY(sensor_data_mutex_); |
| |
| // The set of batch sizes that are subscribed to the sensor. |
| absl::btree_set<const SubscriptionParams*, SubscriptionParams::Compare> |
| subscription_params_ ABSL_GUARDED_BY(sensor_attributes_dynamic_mutex_); |
| |
| mutable absl::Mutex sensor_metrics_mutex_; |
| // The total number of hardware reads. |
| uint64_t total_hardware_read_cnt_ = 0; |
| // The total latency of hardware reads in milliseconds. |
| uint64_t total_hardware_latency_ms_ = 0; |
| // The total software polling start interval in milliseconds. |
| uint64_t total_software_polling_start_interval_ms_ = 0; |
| // The total number of software polling start. |
| uint64_t total_software_polling_start_cnt_ = 0; |
| // The total software polling end interval in milliseconds. |
| uint64_t total_software_polling_end_interval_ms_ = 0; |
| // The total number of software polling end. |
| uint64_t total_software_polling_end_cnt_ = 0; |
| std::chrono::steady_clock::time_point last_refresh_start_time_ = |
| std::chrono::steady_clock::time_point::min(); |
| std::chrono::steady_clock::time_point last_refresh_end_time_ = |
| std::chrono::steady_clock::time_point::min(); |
| }; |
| |
| } // namespace milotic_tlbmc |
| |
| #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_ |