blob: 20f604bf08ec4fa838ea3ae69cffd6437d44b1a7 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fuchsia/camera3/cpp/fidl.h>
#include <lib/sys/inspect/cpp/component.h>
#include <mutex>
#include "src/camera/lib/cobalt_logger/logger.h"
#include "src/lib/fxl/synchronization/thread_annotations.h"
namespace camera {
// |MetricsReporter| handles instrumentation concerns (e.g. exposing information via inspect,
// cobalt, etc) for a camera device instance.
class MetricsReporter {
~MetricsReporter() = default;
// Forward class declarations
class ConfigurationRecord;
class ImageFormatRecord;
class StreamRecord;
class FailureTestRecord;
// Gets a reference to the MetricsReporter object.
// Returns a reference of a static MetricsReporter object. If this is called before
// MetricsReporter::Initialize(), a nop version of MetricsReporter is returned and swallows all
// log requests.
static MetricsReporter& Get();
// Initializes the MetricsReporter object.
// |context| References to the services and connections this component was launched with.
// |enable_cobalt| When this boolean argument is true, MetricsReporter initializes the
// CobaltLogger and report collected metrics.
static void Initialize(sys::ComponentContext& context, bool enable_cobalt)
// Get a reference to the inspector object.
const inspect::Inspector& inspector() FXL_LOCKS_EXCLUDED(mutex_) {
std::lock_guard<std::mutex> lock(mutex_);
return *impl_->inspector_->inspector();
// Creates a ConfigurationRecord object that collects metrics from each device configurations.
// |index| The index of the device configuration that will be associated with this
// ConfigurationRecord object.
// |num_streams| This is the number of streams that the configuration with a given index has.
std::unique_ptr<ConfigurationRecord> CreateConfigurationRecord(uint32_t index,
size_t num_streams);
using FailureTestRecordType = camera__metrics::CameraMetricDimensionFailureTestType;
// Creates a FailureTestRecord representing a potential failure occurrence. When the class is
// destroyed, the occurrence is logged as either failure or non-failure depending on its state at
// the time of destruction. Callers can use the |initial_failure| parameter and ignore the
// returned record to provide immediate-mode recording.
// |type| The failure class for the record.
// |initial_failure| The initial failure state of the record.
// |config_index| If specified, the configuration this failure applies to.
// |stream_index| If specified, the stream this failure applies to.
std::unique_ptr<FailureTestRecord> CreateFailureTestRecord(
FailureTestRecordType type, bool initial_failure = true,
std::optional<uint32_t> config_index = std::nullopt,
std::optional<uint32_t> stream_index = std::nullopt);
explicit MetricsReporter() = default;
explicit MetricsReporter(sys::ComponentContext& context, bool enable_cobalt);
struct Impl {
sys::ComponentContext& context_;
std::unique_ptr<sys::ComponentInspector> inspector_;
inspect::Node node_;
std::unique_ptr<cobalt::Logger> logger_;
explicit Impl(sys::ComponentContext& context);
~Impl() = default;
void InitInspector() FXL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void ConnectToLogger(::fidl::InterfaceRequest<fuchsia::metrics::MetricEventLogger> request);
void RetryConnectingToLogger();
mutable std::mutex mutex_;
std::unique_ptr<Impl> impl_ FXL_GUARDED_BY(mutex_);
// An object of the ImageFormatRecord class stores the output format of an associated stream.
class ImageFormatRecord {
explicit ImageFormatRecord(inspect::Node& parent);
// Stores the image format property.
// |format| Reference to ImageFormat_2 object.
void Set(const fuchsia::sysmem::ImageFormat_2& format);
inspect::Node node_;
inspect::StringProperty pixel_format_;
inspect::StringProperty output_resolution_;
inspect::StringProperty display_resolution_;
inspect::StringProperty color_space_;
inspect::StringProperty pixel_aspect_ratio_;
// An object of the StreamRecord class monitors each stream, collects metrics, and reports them
// via the Cobalt logger if it is enabled. Some of collected metrics are available via the
// Inspect API.
class StreamRecord {
StreamRecord(MetricsReporter::Impl& impl, inspect::Node& parent, uint32_t config_index,
uint32_t stream_index);
// Stores the properties of current stream.
// |props| References to StreamProperties2 object that contains the size information, the
// output format, and the frame rate.
void SetProperties(const fuchsia::camera3::StreamProperties2& props);
// Reports that we've received a new frame.
void FrameReceived();
// Reports that we've dropped/skipped a newly delivered frame.
void FrameDropped(cobalt::FrameDropReason why);
MetricsReporter::Impl& impl_;
zx::time stream_start_;
zx::time stream_stop_;
inspect::Node node_;
inspect::StringProperty frame_rate_;
inspect::BoolProperty supports_crop_region_;
inspect::Node supported_resolutions_node_;
std::vector<inspect::StringProperty> supported_resolutions_;
ImageFormatRecord format_record_;
inspect::UintProperty frames_received_;
inspect::UintProperty frames_dropped_;
cobalt::StreamType type_;
// An object of the ConfigurationRecord class monitors the device configuration associated with
// a given configuration index and collects metrics to report via the Cobalt logger or share via
// the Inspect API.
class ConfigurationRecord {
ConfigurationRecord(MetricsReporter::Impl& impl, uint32_t index, size_t num_streams);
virtual ~ConfigurationRecord() = default;
// Gets a reference to a StreamRecord object associated with a given stream index.
// |index| The index of the stream the caller is interested in.
StreamRecord& GetStreamRecord(uint32_t index) { return stream_records_[index]; }
// Marks the configuration is active or not.
// |active| This boolean value tells whether this configuration is active or not.
void SetActive(bool active) { active_node_.Set(active); }
inspect::Node node_;
inspect::BoolProperty active_node_;
inspect::Node stream_node_;
std::vector<StreamRecord> stream_records_;
// FailureTestRecord records a potential occurrence of a specific class of failure in the camera
// system, and subsequently whether or not the failure actually occurred.
class FailureTestRecord {
explicit FailureTestRecord(MetricsReporter::Impl& impl, FailureTestRecordType type,
bool initial_failure, std::optional<uint32_t> config_index,
std::optional<uint32_t> stream_index);
// Sets the record failure state to the provided value.
void SetFailureState(bool failed);
MetricsReporter::Impl& impl_;
FailureTestRecordType type_;
bool failed_;
camera__metrics::CameraMetricDimensionConfigIndex config_index_;
camera__metrics::CameraMetricDimensionStreamIndex stream_index_;
} // namespace camera
inline constexpr const char kConfigurationInspectorActivePropertyName[] = "active";
inline constexpr const char kConfigurationInspectorNodeName[] = "configurations";
inline constexpr const char kFormatInspectorAspectRatioPropertyName[] = "aspect ratio";
inline constexpr const char kFormatInspectorColorSpacePropertyName[] = "color space";
inline constexpr const char kFormatInspectorDisplayResolutionPropertyName[] = "display resolution";
inline constexpr const char kFormatInspectorOutputResolutionPropertyName[] = "output resolution";
inline constexpr const char kFormatInspectorPixelformatPropertyName[] = "pixel format";
inline constexpr const char kStreamInspectorCropPropertyName[] = "supports crop region";
inline constexpr const char kStreamInspectorFrameratePropertyName[] = "frame rate";
inline constexpr const char kStreamInspectorFramesDroppedPropertyName[] = "frames dropped";
inline constexpr const char kStreamInspectorFramesReceivedPropertyName[] = "frames received";
inline constexpr const char kStreamInspectorImageFormatNodeName[] = "image format";
inline constexpr const char kStreamInspectorNodeName[] = "streams";
inline constexpr const char kStreamInspectorResolutionNodeName[] = "supported resolutions";