blob: 22b2752c1a609f04df7a98e662b1608cd471c58b [file] [log] [blame]
// Copyright 2020 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.
#ifndef SRC_MEDIA_LIB_CODEC_IMPL_INCLUDE_LIB_MEDIA_CODEC_IMPL_CODEC_METRICS_H_
#define SRC_MEDIA_LIB_CODEC_IMPL_INCLUDE_LIB_MEDIA_CODEC_IMPL_CODEC_METRICS_H_
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/sys/cpp/service_directory.h>
#include <memory>
#include <unordered_map>
#include <src/lib/cobalt/cpp/cobalt_event_builder.h>
#include <src/lib/cobalt/cpp/cobalt_logger.h>
#include <src/media/lib/metrics/metrics.cb.h>
// Methods of this class can be called on any thread.
class CodecMetrics final {
public:
// A nop instance so unit tests don't need to wire up cobalt.
CodecMetrics() __TA_EXCLUDES(lock_);
// !service_directory is ok. If !service_directory, the instance will be a nop instance until
// SetServiceDirectory() is called.
CodecMetrics(std::shared_ptr<sys::ServiceDirectory> service_directory) __TA_EXCLUDES(lock_);
~CodecMetrics() __TA_EXCLUDES(lock_);
// Set the ServiceDirectory from which to get fuchsia.cobalt.LoggerFactory. This can be nullptr.
// This can be called again, regardless of whether there was already a previous ServiceDirectory.
// Previously-queued events may be lost (especially recently-queued events) when switching to a
// new ServiceDirectory.
void SetServiceDirectory(std::shared_ptr<sys::ServiceDirectory> service_directory)
__TA_EXCLUDES(lock_);
// Log the event as EVENT_COUNT, with period_duration_micros 0, possibly aggregating with any
// other calls to this method with the same component and event wihtin a short duration to limit
// the rate of FIDL calls to cobalt, per the rate requirement/recommendation in the cobalt docs.
//
// No attempt is made to flush pending events before driver exit or suspend, since this driver
// isn't expected to unbind very often, if ever, and if we're suspending already then it's
// unlikely that the pending cobalt events would be persisted anyway.
void LogEvent(media_metrics::StreamProcessorEvents2MetricDimensionImplementation implementation,
media_metrics::StreamProcessorEvents2MetricDimensionEvent event)
__TA_EXCLUDES(lock_);
private:
class PendingCountsKey {
public:
PendingCountsKey(
media_metrics::StreamProcessorEvents2MetricDimensionImplementation implementation,
media_metrics::StreamProcessorEvents2MetricDimensionEvent event);
media_metrics::StreamProcessorEvents2MetricDimensionImplementation implementation() const;
media_metrics::StreamProcessorEvents2MetricDimensionEvent event() const;
private:
media_metrics::StreamProcessorEvents2MetricDimensionImplementation implementation_;
media_metrics::StreamProcessorEvents2MetricDimensionEvent event_;
};
struct PendingCountsKeyHash {
size_t operator()(const PendingCountsKey& key) const noexcept;
};
struct PendingCountsKeyEqual {
bool operator()(const PendingCountsKey& lhs, const PendingCountsKey& rhs) const noexcept;
};
void TryPostFlushCountsLocked() __TA_REQUIRES(lock_);
void FlushPendingEventCounts() __TA_EXCLUDES(lock_);
static constexpr zx::duration kMinLoggingPeriod = zx::sec(5);
std::mutex lock_;
// We have a separate async::Loop for each instance of cobalt::CobaltLogger, because CobaltLogger
// requires that no async tasks posted by CobaltLogger out-live the CobaltLogger. The easiest way
// to achieve that is to give CobaltLogger its own async::Loop and Quit(), JoinThreads(),
// Shutdown() that async::Loop before destroying the CobaltLogger.
std::unique_ptr<async::Loop> loop_ = nullptr;
std::unique_ptr<cobalt::CobaltLogger> cobalt_logger_ __TA_GUARDED(lock_);
// Don't bother with std::optional<> here - instead subtract kMinLoggingPeriod so we'll log
// immediately the first time.
zx::time last_flushed_ __TA_GUARDED(lock_) = zx::clock::get_monotonic() - kMinLoggingPeriod;
// From component and event to event count.
using PendingCounts =
std::unordered_map<PendingCountsKey, int64_t, PendingCountsKeyHash, PendingCountsKeyEqual>;
PendingCounts pending_counts_ __TA_GUARDED(lock_);
};
#endif // SRC_MEDIA_LIB_CODEC_IMPL_INCLUDE_LIB_MEDIA_CODEC_IMPL_CODEC_METRICS_H_