Refactored metrics to support pull model.

MetricsGroup split into 3 groups, session, engine, and crypto.
MetricsFrontEnd and Report removed.

This is a merge from wvgerrit/28420

Bug: 36217927
Test: Added unit tests to cover modified code.
Change-Id: I2f39f99ce88cc2229d6d1aa9459c67c5b86ccef4
This commit is contained in:
Adam Stone
2017-03-29 17:03:43 -07:00
parent 0a5fe1ffad
commit a34e279d0f
22 changed files with 478 additions and 505 deletions

View File

@@ -18,7 +18,7 @@
#include "lock.h"
#include "distribution.h"
#include "metric_publisher.h"
#include "metric_serialization.h"
namespace wvcdm {
namespace metrics {
@@ -27,11 +27,11 @@ class EventMetricTest;
// This base class provides the common defintion used by all templated
// instances of EventMetric.
class BaseEventMetric : public MetricPublisher {
class BaseEventMetric : public MetricSerializable {
public:
// Publish metric values to the MetricNotification. |subscriber| must
// Send metric values to the MetricSerializer. |serializer| must
// not be null and is owned by the caller.
virtual void Publish(MetricNotification* subscriber);
virtual void Serialize(MetricSerializer* serializer);
protected:
// Instantiates a BaseEventMetric.

View File

@@ -1,46 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// This file contains the declarations for the Metric class and related
// types.
#ifndef WVCDM_METRICS_METRIC_PUBLISHER_H_
#define WVCDM_METRICS_METRIC_PUBLISHER_H_
namespace wvcdm {
namespace metrics {
// The MetricNotification is implemented by the code that instantiates
// MetricPublisher instances. The caller provides this MetricNotification
// instance to MetricPublisher::Publish. In turn, Publish will make a call to
// UpdateMetric for each value to be published. The Metric may contain zero or
// more values to be updated.
class MetricNotification {
public:
virtual ~MetricNotification() {};
// The metric_id is the metric name, plus the metric part name, and the
// metric field name/value string. E.g.
// name: "drm/cdm/decrypt/duration"
// part: "mean"
// field name/value string: "{error_code:0&buffer_size:1024}"
// becomes: "drm/cdm/decrypt/duration/mean/{error_code:0&buffer_size:1024}".
virtual void UpdateString(const std::string& metric_id,
const std::string& value) = 0;
virtual void UpdateInt32(const std::string& metric_id, int32_t value) = 0;
virtual void UpdateInt64(const std::string& metric_id, int64_t value) = 0;
virtual void UpdateDouble(const std::string& metric_id, double value) = 0;
};
// This abstract class merely provides the definition for publishing the value
// of the metric.
class MetricPublisher {
public:
virtual ~MetricPublisher() { }
// Publish metric values to the MetricNotification. |subscriber| must
// not be null and is owned by the caller.
virtual void Publish(MetricNotification* subscriber) = 0;
};
} // namespace metrics
} // namespace wvcdm
#endif // WVCDM_METRICS_METRIC_PUBLISHER_H_

View File

@@ -0,0 +1,46 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// This file contains the declarations for the Metric class and related
// types.
#ifndef WVCDM_METRICS_METRIC_SERIALIZATION_H_
#define WVCDM_METRICS_METRIC_SERIALIZATION_H_
namespace wvcdm {
namespace metrics {
// The MetricSerializer is implemented by the code that instantiates
// MetricSerializable instances. The caller provides this MetricSerializer
// instance to MetricSerializable::Serialize. In turn, Serialize will make a
// call to Set* for each value to be Serialized. The MetricSerialiable
// implementation may set zero or more values on the MetricSerializer.
class MetricSerializer {
public:
virtual ~MetricSerializer() {};
// The metric_id is the metric name, plus the metric part name, and the
// metric field name/value string. E.g.
// name: "drm/cdm/decrypt/duration"
// part: "mean"
// field name/value string: "{error_code:0&buffer_size:1024}"
// becomes: "drm/cdm/decrypt/duration/mean/{error_code:0&buffer_size:1024}".
virtual void SetString(const std::string& metric_id,
const std::string& value) = 0;
virtual void SetInt32(const std::string& metric_id, int32_t value) = 0;
virtual void SetInt64(const std::string& metric_id, int64_t value) = 0;
virtual void SetDouble(const std::string& metric_id, double value) = 0;
};
// This abstract class merely provides the definition for serializing the value
// of the metric.
class MetricSerializable {
public:
virtual ~MetricSerializable() { }
// Serialize metric values to the MetricSerializer. |serializer| must
// not be null and is owned by the caller.
virtual void Serialize(MetricSerializer* serializer) = 0;
};
} // namespace metrics
} // namespace wvcdm
#endif // WVCDM_METRICS_METRIC_SERIALIZATION_H_

View File

@@ -1,4 +1,7 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// This file contains definitions for metrics being collected throughout the
// CDM.
#ifndef WVCDM_METRICS_METRICS_GROUP_H_
#define WVCDM_METRICS_METRICS_GROUP_H_
@@ -6,14 +9,52 @@
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENC.h"
#include "event_metric.h"
#include "metric_publisher.h"
#include "OEMCryptoCENC.h"
#include "wv_cdm_types.h"
// This definition indicates that a given metric does not need timing
// stats. Example:
//
// M_RECORD(my_metrics, my_metric_name, NO_TIME);
#define NO_TIME 0
// Used to record metric timing and additional information about a specific
// event. Assumes that a microsecond timing has been provided. Example:
//
// long total_time = 0;
// long error_code = TimeSomeOperation(&total_time);
// M_RECORD(my_metrics, my_metric_name, total_time, error_code);
#define M_RECORD(GROUP, METRIC, TIME, ...) \
if ( GROUP ) { \
( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \
}
// This definition automatically times an operation and records the time and
// additional information such as error code to the provided metric.
// Example:
//
// OEMCryptoResult sts;
// M_TIME(
// sts = OEMCrypto_Initialize(),
// my_metrics_collection,
// oemcrypto_initialize_,
// sts);
#define M_TIME(CALL, GROUP, METRIC, ...) \
if ( GROUP ) { \
wvcdm::metrics::TimerMetric timer; \
timer.Start(); \
CALL; \
( GROUP ) -> METRIC . Record(timer.AsUs(), ##__VA_ARGS__ ); \
} else { \
CALL; \
}
namespace wvcdm {
namespace metrics {
// This enum defines the conditions encountered during OEMCrypto Initialization
// in oemcrypto_adapter_dynamic.
typedef enum OEMCryptoInitializationMode {
OEMCrypto_INITIALIZED_USING_IN_APP = 0,
OEMCrypto_INITIALIZED_FORCING_L3 = 1,
@@ -33,35 +74,12 @@ typedef enum OEMCryptoInitializationMode {
OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0 = 15
} OEMCryptoInitializationMode;
/*
* The metrics group is the group of all metrics that be be recorded. They
* are kept together to allow calls to be correlated to one another.
*/
class MetricsGroup {
// This class contains metrics for Crypto Session and OEM Crypto.
class CryptoMetrics {
public:
/* CDM ENGINE */
EventMetric<CdmResponseType> cdm_engine_add_key_;
EventMetric<CdmResponseType> cdm_engine_close_session_;
EventMetric<CdmResponseType> cdm_engine_decrypt_;
EventMetric<bool> cdm_engine_find_session_for_key_;
EventMetric<CdmResponseType> cdm_engine_generate_key_request_;
EventMetric<CdmResponseType> cdm_engine_get_provisioning_request_;
EventMetric<CdmResponseType> cdm_engine_get_usage_info_;
EventMetric<CdmResponseType> cdm_engine_handle_provisioning_response_;
EventMetric<> cdm_engine_life_span_;
EventMetric<CdmResponseType> cdm_engine_open_key_set_session_;
EventMetric<CdmResponseType> cdm_engine_open_session_;
EventMetric<CdmResponseType> cdm_engine_query_key_status_;
EventMetric<CdmResponseType> cdm_engine_release_all_usage_info_;
EventMetric<CdmResponseType> cdm_engine_release_usage_info_;
EventMetric<CdmResponseType> cdm_engine_remove_keys_;
EventMetric<CdmResponseType> cdm_engine_restore_key_;
EventMetric<CdmResponseType, CdmSecurityLevel> cdm_engine_unprovision_;
/* CDM SESSION */
EventMetric<> cdm_session_life_span_;
EventMetric<CdmResponseType> cdm_session_renew_key_;
EventMetric<CdmResponseType> cdm_session_restore_offline_session_;
EventMetric<CdmResponseType> cdm_session_restore_usage_session_;
CryptoMetrics();
/* CRYPTO SESSION */
EventMetric<CdmResponseType> crypto_session_delete_all_usage_reports_;
EventMetric<CdmResponseType> crypto_session_delete_multiple_usage_information_;
@@ -127,14 +145,99 @@ class MetricsGroup {
/* Internal OEMCrypto Metrics */
EventMetric<OEMCryptoInitializationMode> oemcrypto_initialization_mode_;
EventMetric<uint32_t, uint32_t> oemcrypto_l1_api_version_;
};
MetricsGroup();
~MetricsGroup();
// This class contains session-scoped metrics. All properties and
// statistics related to operations within a single session are
// recorded here.
class SessionMetrics {
public:
SessionMetrics();
// Sets the session id of the metrics group. This allows the session
// id to be captured and reported as part of the collection of metrics.
void SetSessionId(const CdmSessionId& session_id) {
session_id_ = session_id; }
// Returns the session id or an empty session id if it has not been set.
const CdmSessionId& GetSessionId() const { return session_id_; }
// Marks the metrics object as completed and ready for serialization.
void SetCompleted() { completed_ = true; }
// Returns true if the object is completed. This is used to determine
// when the stats are ready to be published.
bool IsCompleted() const { return completed_; }
// Returns a pointer to the crypto metrics belonging to the engine instance.
// This instance retains ownership of the object.
CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; }
// Metrics collected at the session level.
EventMetric<> cdm_session_life_span_;
EventMetric<CdmResponseType> cdm_session_renew_key_;
EventMetric<CdmResponseType> cdm_session_restore_offline_session_;
EventMetric<CdmResponseType> cdm_session_restore_usage_session_;
private:
void Publish(MetricNotification* subscriber);
CdmSessionId session_id_;
bool completed_;
CryptoMetrics crypto_metrics_;
};
// This class contains engine-scoped metrics. All properties and
// statistics related to operations within the engine, but outside
// the scope of a session are recorded here.
class EngineMetrics {
public:
EngineMetrics();
~EngineMetrics();
// Add a new SessionMetrics instance and return a pointer to the caller.
// The new SessionMetrics instance is owned by this EngineMetrics instance
// and will exist until RemoveSession is called or this object is deleted.
SessionMetrics* AddSession();
// Removes the metrics object for the given session id. This should only
// be called when the SessionMetrics instance is no longer in use.
void RemoveSession(CdmSessionId session_id);
// Returns a pointer to the crypto metrics belonging to the engine instance.
// The CryptoMetrics instance is still owned by this object and will exist
// until this object is deleted.
CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; }
// Serialize all engine and completed session metrics to json format and
// send them to the output string. |out| must NOT be null. |completed_only|
// indicates that this call should only publish SessionMetrics instances
// that are marked as completed.
void JsonSerialize(std::string* out, bool completed_only);
// Metrics recorded at the engine level.
EventMetric<CdmResponseType> cdm_engine_add_key_;
EventMetric<CdmResponseType> cdm_engine_close_session_;
EventMetric<CdmResponseType> cdm_engine_decrypt_;
EventMetric<bool> cdm_engine_find_session_for_key_;
EventMetric<CdmResponseType> cdm_engine_generate_key_request_;
EventMetric<CdmResponseType> cdm_engine_get_provisioning_request_;
EventMetric<CdmResponseType> cdm_engine_get_usage_info_;
EventMetric<CdmResponseType> cdm_engine_handle_provisioning_response_;
EventMetric<> cdm_engine_life_span_;
EventMetric<CdmResponseType> cdm_engine_open_key_set_session_;
EventMetric<CdmResponseType> cdm_engine_open_session_;
EventMetric<CdmResponseType> cdm_engine_query_key_status_;
EventMetric<CdmResponseType> cdm_engine_release_all_usage_info_;
EventMetric<CdmResponseType> cdm_engine_release_usage_info_;
EventMetric<CdmResponseType> cdm_engine_remove_keys_;
EventMetric<CdmResponseType> cdm_engine_restore_key_;
EventMetric<CdmResponseType, CdmSecurityLevel> cdm_engine_unprovision_;
private:
Lock session_metrics_lock_;
std::vector<metrics::SessionMetrics*> session_metrics_list_;
CryptoMetrics crypto_metrics_;
};
} // namespace metrics
} // namespace wvcdm
#endif

View File

@@ -1,58 +0,0 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#ifndef WVCDM_METRICS_METRICS_FRONT_END_H_
#define WVCDM_METRICS_METRICS_FRONT_END_H_
#include <map>
#include "report.h"
#include "timer_metric.h" /* needed for the macro */
namespace wvcdm {
namespace metrics {
class MetricsFrontEnd {
public:
MetricsFrontEnd(Report* root);
MetricNotification* CreateSubscriber();
static MetricsFrontEnd& Instance();
static void OverrideInstance(MetricsFrontEnd* instance);
private:
static MetricsFrontEnd* instance_;
Report* root_;
/* Disallow copy and assign. */
MetricsFrontEnd(const MetricsFrontEnd&);
void operator=(const MetricsFrontEnd&);
};
} // namespace metrics
} // namespace wvcdm
#define MFE wvcdm::metrics::MetricsFrontEnd::Instance()
#define NO_TIME 0
#define M_RECORD(GROUP, METRIC, TIME, ...) \
if ( GROUP ) { \
( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \
}
#define M_TIME(CALL, GROUP, METRIC, ...) \
if ( GROUP ) { \
wvcdm::metrics::TimerMetric timer; \
timer.Start(); \
CALL; \
( GROUP ) -> METRIC . Record(timer.AsUs(), ##__VA_ARGS__ ); \
} else { \
CALL; \
}
#endif

View File

@@ -1,29 +0,0 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#ifndef WVCDM_METRICS_REPORT_H_
#define WVCDM_METRICS_REPORT_H_
#include <stdint.h>
#include "event_metric.h"
namespace wvcdm {
namespace metrics {
class Report : public MetricNotification {
public:
virtual ~Report() { }
/* Create a new report of the same type. The new report is not
* a copy of this report. The pointer is to be owned by whoever
* calls this function. */
virtual Report* NewReport() const;
};
} // metrics
} //wvcdm
#endif