Add product name as a system profile field.
Change-Id: Id2e7fab040054d233050e25ce24ff094892dfefe
diff --git a/analyzer/report_master/report_serializer.cc b/analyzer/report_master/report_serializer.cc
index 4106f26..ecfe894 100644
--- a/analyzer/report_master/report_serializer.cc
+++ b/analyzer/report_master/report_serializer.cc
@@ -496,6 +496,9 @@
case cobalt::SystemProfileField::BOARD_NAME:
(*stream) << "Board_Name";
break;
+ case cobalt::SystemProfileField::PRODUCT_NAME:
+ (*stream) << "Product_Name";
+ break;
}
}
return grpc::Status::OK;
@@ -600,6 +603,9 @@
case SystemProfileField::BOARD_NAME:
(*stream) << ToCSVString(profile.board_name());
break;
+ case SystemProfileField::PRODUCT_NAME:
+ (*stream) << ToCSVString(profile.product_name());
+ break;
}
}
}
diff --git a/analyzer/report_master/report_serializer_test.cc b/analyzer/report_master/report_serializer_test.cc
index 58f742a..157b1b2 100644
--- a/analyzer/report_master/report_serializer_test.cc
+++ b/analyzer/report_master/report_serializer_test.cc
@@ -30,6 +30,7 @@
const uint32_t kGroupedFruitHistogramReportConfigId = 6;
const uint32_t kGroupedRawDumpReportConfigId = 7;
const uint32_t kGroupedByBoardNameRawDumpReportConfigId = 8;
+const uint32_t kGroupedByProductNameRawDumpReportConfigId = 9;
const char* kReportConfigText = R"(
element {
@@ -171,6 +172,31 @@
}
system_profile_field: [BOARD_NAME]
}
+
+element {
+ customer_id: 1
+ project_id: 1
+ id: 9
+ metric_id: 1
+ report_type: RAW_DUMP
+ variable {
+ metric_part: "City"
+ }
+ variable {
+ metric_part: "Fruit"
+ }
+ variable {
+ metric_part: "Minutes"
+ }
+ variable {
+ metric_part: "Rating"
+ }
+ export_configs {
+ csv {}
+ }
+ system_profile_field: [PRODUCT_NAME]
+}
+
)";
ReportMetadataLite BuildHistogramMetadata(uint32_t variable_index) {
@@ -201,6 +227,7 @@
}
void FillSystemProfile(SystemProfile* profile) {
+ profile->set_product_name("ReportSerializerTest");
profile->set_board_name("ReportSerializerTest");
profile->set_arch(SystemProfile::X86_64);
profile->set_os(SystemProfile::FUCHSIA);
@@ -386,7 +413,7 @@
std::string mime_type;
std::string report;
- // Test firt using the method SerializeReport().
+ // Test first using the method SerializeReport().
auto status = SerializeRawDumpReport(report_config_id, variable_indices,
report_rows, &report, &mime_type);
EXPECT_TRUE(status.ok()) << status.error_message() << " ";
@@ -522,6 +549,25 @@
}
// Tests the function SerializeReport in the case that the
+// report is a raw dump report with several row added and system profile set.
+TEST_F(ReportSerializerTest, SerializeGroupedByProductNameRawDumpReportToCSV) {
+ std::vector<ReportRow> report_rows;
+ report_rows.push_back(BuildRawDumpReportRow("New York", "Apple", 42, 3.14));
+ report_rows.push_back(BuildRawDumpReportRow("Chicago", "Pear", -1, 2.718281));
+ report_rows.push_back(
+ BuildRawDumpReportRow("Miami", "Coconut", 9999999, 1.41421356237309504));
+ const char* kExpectedCSV =
+ R"(date,City,Fruit,Minutes,Rating,Product_Name
+2035-10-22,"New York","Apple",42,3.140,"ReportSerializerTest"
+2035-10-22,"Chicago","Pear",-1,2.718,"ReportSerializerTest"
+2035-10-22,"Miami","Coconut",9999999,1.414,"ReportSerializerTest"
+)";
+ DoSerializeRawDumpReportTest(kGroupedByProductNameRawDumpReportConfigId,
+ {0, 1, 2, 3}, report_rows, "text/csv",
+ kExpectedCSV);
+}
+
+// Tests the function SerializeReport in the case that the
// report is a histogram report with rows added whose values are integers,
// and the export is to csv.
TEST_F(ReportSerializerTest, SerializeHistogramReportToCSVIntegerRows) {
diff --git a/analyzer/store/observation_store.cc b/analyzer/store/observation_store.cc
index 63b9f6c..3979817 100644
--- a/analyzer/store/observation_store.cc
+++ b/analyzer/store/observation_store.cc
@@ -234,6 +234,9 @@
case SystemProfileField::BOARD_NAME:
dst->set_allocated_board_name(src->release_board_name());
break;
+ case SystemProfileField::PRODUCT_NAME:
+ dst->set_allocated_product_name(src->release_product_name());
+ break;
}
}
}
diff --git a/config/metrics.proto b/config/metrics.proto
index 1609282..0ed7aed 100644
--- a/config/metrics.proto
+++ b/config/metrics.proto
@@ -25,6 +25,7 @@
OS = 0;
ARCH = 1;
BOARD_NAME = 2;
+ PRODUCT_NAME = 3;
}
// ExponentialIntegerBuckets is used to define a partition of the integers into
diff --git a/encoder/encoder.cc b/encoder/encoder.cc
index 9204a2d..848b95c 100644
--- a/encoder/encoder.cc
+++ b/encoder/encoder.cc
@@ -414,6 +414,10 @@
result.metadata->mutable_system_profile()->set_board_name(
profile.board_name());
break;
+ case SystemProfileField::PRODUCT_NAME:
+ result.metadata->mutable_system_profile()->set_product_name(
+ profile.product_name());
+ break;
}
}
}
diff --git a/encoder/encoder_test.cc b/encoder/encoder_test.cc
index f94b1eb..6d8677b 100644
--- a/encoder/encoder_test.cc
+++ b/encoder/encoder_test.cc
@@ -57,6 +57,7 @@
system_profile_.set_os(SystemProfile::FUCHSIA);
system_profile_.set_arch(SystemProfile::ARM_64);
system_profile_.set_board_name("Testing Board");
+ system_profile_.set_product_name("Testing Product");
}
const SystemProfile& system_profile() const override {
@@ -164,6 +165,14 @@
} else {
EXPECT_EQ("", result.metadata->system_profile().board_name());
}
+
+ if (std::find(fields.begin(), fields.end(),
+ SystemProfileField::PRODUCT_NAME) != fields.end()) {
+ EXPECT_EQ("Testing Product",
+ result.metadata->system_profile().product_name());
+ } else {
+ EXPECT_EQ("", result.metadata->system_profile().product_name());
+ }
}
// Tests the EncodeString() method using the given |value| and the given
diff --git a/encoder/encoder_test_config.yaml b/encoder/encoder_test_config.yaml
index 06e88d8..ede9d0d 100644
--- a/encoder/encoder_test_config.yaml
+++ b/encoder/encoder_test_config.yaml
@@ -99,6 +99,17 @@
- ARCH
- OS
+# Metric 12 has a single string part and 4 system_profile_field selectors.
+- id: 12
+ time_zone_policy: LOCAL
+ parts:
+ "Part1":
+ system_profile_field:
+ - BOARD_NAME
+ - ARCH
+ - OS
+ - PRODUCT_NAME
+
################################################################################
# EncodingConfigs
################################################################################
diff --git a/encoder/system_data.cc b/encoder/system_data.cc
index 764e2d0..c02f142 100644
--- a/encoder/system_data.cc
+++ b/encoder/system_data.cc
@@ -83,7 +83,10 @@
} // namespace
-SystemData::SystemData() { PopulateSystemProfile(); }
+SystemData::SystemData(const std::string& product_name) {
+ system_profile_.set_product_name(product_name);
+ PopulateSystemProfile();
+}
void SystemData::OverrideSystemProfile(const SystemProfile& profile) {
system_profile_ = profile;
diff --git a/encoder/system_data.h b/encoder/system_data.h
index b948be0..0284f36 100644
--- a/encoder/system_data.h
+++ b/encoder/system_data.h
@@ -5,6 +5,8 @@
#ifndef COBALT_ENCODER_SYSTEM_DATA_H_
#define COBALT_ENCODER_SYSTEM_DATA_H_
+#include <string>
+
#include "./observation.pb.h"
namespace cobalt {
@@ -25,8 +27,8 @@
class SystemData : public SystemDataInterface {
public:
// Constructor: Populuates system_profile_ with the real SystemProfile
- // of the actual running system.
- SystemData();
+ // of the actual running system and the specified product name.
+ explicit SystemData(const std::string& product_name);
virtual ~SystemData() = default;
diff --git a/encoder/system_data_test.cc b/encoder/system_data_test.cc
index 119be46..80eeb19 100644
--- a/encoder/system_data_test.cc
+++ b/encoder/system_data_test.cc
@@ -16,10 +16,11 @@
namespace encoder {
TEST(SystemDataTest, BasicTest) {
- SystemData system_data;
+ SystemData system_data("test_product");
EXPECT_NE(SystemProfile::UNKNOWN_OS, system_data.system_profile().os());
EXPECT_NE(SystemProfile::UNKNOWN_ARCH, system_data.system_profile().arch());
EXPECT_NE(system_data.system_profile().board_name(), "");
+ EXPECT_EQ(system_data.system_profile().product_name(), "test_product");
// Board names we expect to see.
std::set<std::string> expected_board_names = {"Eve", "Generic ARM"};
diff --git a/observation.proto b/observation.proto
index 963e90c..af2f47f 100644
--- a/observation.proto
+++ b/observation.proto
@@ -140,6 +140,13 @@
// This is a string representing the board name of the device. If a board name
// cannot be determined, then this field will be 'unknown:<cpu signature>'.
string board_name = 4;
+
+ // This is a string representing the source of the observation.
+ // For now, this is going to refer to layers of the Fuchsia cake such as
+ // "garnet", "zircon", "topaz", etc... In the future, we will use something
+ // related to what sort of device we are running on, such as
+ // "Google Lightbulb X" or "Android Laptop III".
+ string product_name = 5;
}
// An Observation consists of one or more ObservationParts.
diff --git a/tools/test_app/test_app.cc b/tools/test_app/test_app.cc
index 6466abc..470de79 100644
--- a/tools/test_app/test_app.cc
+++ b/tools/test_app/test_app.cc
@@ -510,7 +510,7 @@
shuffler_encryption_scheme = EncryptedMessage::HYBRID_ECDH_V1;
}
- std::unique_ptr<SystemData> system_data(new SystemData());
+ std::unique_ptr<SystemData> system_data(new SystemData("test_app"));
if (!FLAGS_override_board_name.empty()) {
SystemProfile profile;
profile.set_os(SystemProfile::FUCHSIA);