Collect android metrics for bytes downloaded
Report bytes downloaded for update attempts and successful updates.
Prefs used to help metrics report:
kPrefsCurrentBytesDownloaded
kPrefsTotalBytesDownloaded
Bug: 30989466
Test: unittest pass
Change-Id: I7d213204ee2757551ad914c122a274965dfbff06
diff --git a/common/test_utils.h b/common/test_utils.h
index ba9f5f2..ddb3d34 100644
--- a/common/test_utils.h
+++ b/common/test_utils.h
@@ -31,6 +31,7 @@
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/files/scoped_temp_dir.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "update_engine/common/action.h"
@@ -101,6 +102,11 @@
void FillWithData(brillo::Blob* buffer);
+// Compare the value of native array for download source parameter.
+MATCHER_P(DownloadSourceMatcher, source_array, "") {
+ return std::equal(source_array, source_array + kNumDownloadSources, arg);
+}
+
// Class to unmount FS when object goes out of scope
class ScopedFilesystemUnmounter {
public:
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index c47e389..e469d2f 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -103,11 +103,6 @@
EXPECT_EQ(expected_response_sign, stored_response_sign);
}
-// Compare the value of native array for download source parameter.
-MATCHER_P(DownloadSourceMatcher, source_array, "") {
- return memcmp(source_array, arg, kNumDownloadSources) == 0;
-}
-
class PayloadStateTest : public ::testing::Test { };
TEST(PayloadStateTest, SetResponseWorksWithEmptyResponse) {
@@ -917,7 +912,15 @@
EXPECT_CALL(*fake_system_state.mock_metrics_reporter(),
ReportSuccessfulUpdateMetrics(
- _, _, _, _, DownloadSourceMatcher(total_bytes), _, _, _, _))
+ _,
+ _,
+ _,
+ _,
+ test_utils::DownloadSourceMatcher(total_bytes),
+ _,
+ _,
+ _,
+ _))
.Times(1);
payload_state.UpdateSucceeded();
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 6d67000..7dcbeec 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -372,6 +372,16 @@
} else {
ProgressUpdate(progress);
}
+
+ // Update the bytes downloaded in prefs.
+ int64_t current_bytes_downloaded =
+ metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
+ int64_t total_bytes_downloaded =
+ metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
+ prefs_->SetInt64(kPrefsCurrentBytesDownloaded,
+ current_bytes_downloaded + bytes_progressed);
+ prefs_->SetInt64(kPrefsTotalBytesDownloaded,
+ total_bytes_downloaded + bytes_progressed);
}
bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
@@ -446,6 +456,8 @@
ClearMetricsPrefs();
if (error_code == ErrorCode::kSuccess) {
metrics_utils::SetSystemUpdatedMarker(clock_.get(), prefs_);
+ // Clear the total bytes downloaded if and only if the update succeeds.
+ prefs_->SetInt64(kPrefsTotalBytesDownloaded, 0);
}
}
@@ -570,18 +582,43 @@
attempt_result,
error_code);
+ int64_t current_bytes_downloaded =
+ metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
+ metrics_reporter_->ReportUpdateAttemptDownloadMetrics(
+ current_bytes_downloaded,
+ 0,
+ DownloadSource::kNumDownloadSources,
+ metrics::DownloadErrorCode::kUnset,
+ metrics::ConnectionType::kUnset);
+
if (error_code == ErrorCode::kSuccess) {
int64_t reboot_count =
metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
string build_version;
prefs_->GetString(kPrefsPreviousVersion, &build_version);
+
+ // For android metrics, we only care about the total bytes downloaded
+ // for all sources; for now we assume the only download source is
+ // HttpsServer.
+ int64_t total_bytes_downloaded =
+ metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
+ int64_t num_bytes_downloaded[kNumDownloadSources] = {};
+ num_bytes_downloaded[DownloadSource::kDownloadSourceHttpsServer] =
+ total_bytes_downloaded;
+
+ int download_overhead_percentage = 0;
+ if (current_bytes_downloaded > 0) {
+ download_overhead_percentage =
+ (total_bytes_downloaded - current_bytes_downloaded) * 100ull /
+ current_bytes_downloaded;
+ }
metrics_reporter_->ReportSuccessfulUpdateMetrics(
static_cast<int>(attempt_number),
0, // update abandoned count
payload_type,
payload_size,
- nullptr, // num bytes downloaded
- 0, // download overhead percentage
+ num_bytes_downloaded,
+ download_overhead_percentage,
duration,
static_cast<int>(reboot_count),
0); // url_switch_count
@@ -657,6 +694,7 @@
void UpdateAttempterAndroid::ClearMetricsPrefs() {
CHECK(prefs_);
+ prefs_->Delete(kPrefsCurrentBytesDownloaded);
prefs_->Delete(kPrefsNumReboots);
prefs_->Delete(kPrefsPayloadAttemptNumber);
prefs_->Delete(kPrefsSystemUpdatedMarker);
diff --git a/update_attempter_android.h b/update_attempter_android.h
index 911ab81..28bf90a 100644
--- a/update_attempter_android.h
+++ b/update_attempter_android.h
@@ -128,6 +128,10 @@
// |KprefsNumReboots|: number of reboots when applying the current update.
// |kPrefsSystemUpdatedMarker|: end timestamp of the last successful update.
// |kPrefsUpdateTimestampStart|: start timestamp of the current update.
+ // |kPrefsCurrentBytesDownloaded|: number of bytes downloaded for the current
+ // payload_id.
+ // |kPrefsTotalBytesDownloaded|: number of bytes downloaded in total since
+ // the last successful update.
// Metrics report function to call:
// |ReportUpdateAttemptMetrics|
@@ -149,7 +153,8 @@
// Prefs to delete:
// |kPrefsNumReboots|, |kPrefsPayloadAttemptNumber|,
- // |kPrefsSystemUpdatedMarker|, |kPrefsUpdateTimestampStart|
+ // |kPrefsSystemUpdatedMarker|, |kPrefsUpdateTimestampStart|,
+ // |kPrefsCurrentBytesDownloaded|
void ClearMetricsPrefs();
DaemonStateInterface* daemon_state_;
diff --git a/update_attempter_android_unittest.cc b/update_attempter_android_unittest.cc
index ac6cec2..94452df 100644
--- a/update_attempter_android_unittest.cc
+++ b/update_attempter_android_unittest.cc
@@ -28,6 +28,7 @@
#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/fake_prefs.h"
#include "update_engine/common/mock_action_processor.h"
+#include "update_engine/common/test_utils.h"
#include "update_engine/common/utils.h"
#include "update_engine/daemon_state_android.h"
#include "update_engine/mock_metrics_reporter.h"
@@ -38,6 +39,7 @@
using update_engine::UpdateStatus;
namespace chromeos_update_engine {
+
class UpdateAttempterAndroidTest : public ::testing::Test {
protected:
UpdateAttempterAndroidTest() = default;
@@ -150,4 +152,58 @@
EXPECT_TRUE(prefs_.Exists(kPrefsSystemUpdatedMarker));
}
+TEST_F(UpdateAttempterAndroidTest, ReportMetricsForBytesDownloaded) {
+ // Check both prefs are updated correctly.
+ update_attempter_android_.BytesReceived(20, 50, 200);
+ EXPECT_EQ(
+ 20,
+ metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, &prefs_));
+ EXPECT_EQ(
+ 20,
+ metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
+
+ EXPECT_CALL(*metrics_reporter_,
+ ReportUpdateAttemptDownloadMetrics(50, _, _, _, _))
+ .Times(1);
+ EXPECT_CALL(*metrics_reporter_,
+ ReportUpdateAttemptDownloadMetrics(40, _, _, _, _))
+ .Times(1);
+
+ int64_t total_bytes[kNumDownloadSources] = {};
+ total_bytes[kDownloadSourceHttpsServer] = 90;
+ EXPECT_CALL(*metrics_reporter_,
+ ReportSuccessfulUpdateMetrics(
+ _,
+ _,
+ _,
+ _,
+ test_utils::DownloadSourceMatcher(total_bytes),
+ 125,
+ _,
+ _,
+ _))
+ .Times(1);
+
+ // The first update fails after receving 50 bytes in total.
+ update_attempter_android_.BytesReceived(30, 50, 200);
+ update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kError);
+ EXPECT_EQ(
+ 0,
+ metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, &prefs_));
+ EXPECT_EQ(
+ 50,
+ metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
+
+ // The second update succeeds after receiving 40 bytes, which leads to a
+ // overhead of 50 / 40 = 125%.
+ update_attempter_android_.BytesReceived(40, 40, 50);
+ update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
+ // Both prefs should be cleared.
+ EXPECT_EQ(
+ 0,
+ metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, &prefs_));
+ EXPECT_EQ(
+ 0, metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
+}
+
} // namespace chromeos_update_engine