blob: dc87f9fde8476da0a702c2f4930c896d2a20d2c1 [file] [log] [blame]
// Copyright 2018 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 <lib/async-loop/cpp/loop.h>
#include <lib/inspect/component.h>
#include <lib/sys/cpp/component_context.h>
#include <src/lib/fxl/command_line.h>
#include <src/lib/fxl/log_settings_command_line.h>
#include <src/lib/fxl/strings/string_printf.h>
#include <variant>
#include <vector>
#include "lib/inspect/inspect.h"
size_t current_suffix = 0;
void ResetUniqueNames() { current_suffix = 0; }
std::string UniqueName(const char* name) {
return fxl::StringPrintf("%s:0x%lx", name, current_suffix++);
}
// A single cell in the table.
// Cells expose a string property, an int metric, and a double metric.
class Cell {
public:
Cell(const std::string& name, int64_t value, double double_value,
inspect::Object obj)
: object_(std::move(obj)) {
name_ = object_.CreateStringProperty("name", name);
value_ = object_.CreateIntMetric("value", value);
double_value_ = object_.CreateDoubleMetric("double_value", double_value);
}
private:
inspect::Object object_;
inspect::StringProperty name_;
inspect::IntMetric value_;
inspect::DoubleMetric double_value_;
};
// A row in the table, contains cells.
class Row {
public:
explicit Row(inspect::Object obj) : object_(std::move(obj)) {}
Row(Row&&) = default;
Row& operator=(Row&&) = default;
Cell* AddCell(const std::string& name, int64_t value, double double_value) {
// Construct a new cell in-place, and expose it as a child of this object in
// the Inspect output.
cells_.push_back(Cell(name, value, double_value,
object_.CreateChild(UniqueName("cell"))));
return &(*cells_.rbegin());
}
private:
inspect::Object object_;
std::vector<Cell> cells_;
};
// A table, contains rows.
class Table {
public:
Table(int row_count, int col_count, inspect::Object obj)
: object_(std::move(obj)) {
object_name_ = object_.CreateStringProperty("object_name", "Example Table");
binary_data_ = object_.CreateByteVectorProperty(
"binary_data", std::vector<uint8_t>({0x20, 0x0, 0x11, 0x12, 0x5}));
binary_key_ = object_.CreateStringProperty(
std::string("\x05\x01\x03", 3),
"The key of this value is a binary value.");
binary_key_and_data_ = object_.CreateByteVectorProperty(
std::string("\x05\x01\x02", 3), std::vector<uint8_t>({0x1, 0x2}));
// Add default rows and columns to the table.
const int total = row_count * col_count;
int idx = 0;
for (int i = 0; i < row_count; ++i) {
Row* row = AddRow();
for (int j = 0; j < col_count; ++j) {
// name is "(row,col)", value is i*j, and double_value is percentage
// done.
row->AddCell(fxl::StringPrintf("(%d,%d)", i, j), i * j,
100.0 * (++idx) / total);
}
}
}
Row* AddRow() {
// Construct a new row in-place, and expose it as a child of this object in
// the Inspect output.
rows_.push_back(Row(object_.CreateChild(UniqueName("row"))));
return &(*rows_.rbegin());
}
private:
inspect::Object object_;
inspect::StringProperty object_name_;
inspect::ByteVectorProperty binary_data_;
inspect::StringProperty binary_key_;
inspect::ByteVectorProperty binary_key_and_data_;
std::vector<Row> rows_;
};
template <typename HistogramType, typename NumericType>
HistogramType PopulatedHistogram(HistogramType histogram, NumericType floor,
NumericType step, size_t count) {
for (size_t i = 0; i < count; i++) {
histogram.Insert(floor);
floor += step;
}
return histogram;
}
int main(int argc, char** argv) {
auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
fxl::SetLogSettingsFromCommandLine(command_line);
// Construct a demo table with the rows and columns given on the command line.
auto rows = command_line.GetOptionValueWithDefault("rows", "");
auto columns = command_line.GetOptionValueWithDefault("columns", "");
if (rows.empty() || columns.empty() || atoi(rows.c_str()) == 0 ||
atoi(columns.c_str()) == 0) {
fprintf(stderr, R"text(Usage: %s --rows=N --columns=M
Example component to showcase Inspect API objects, including an NxM
nested table.
)text",
argv[0]);
return 1;
}
// Exposing objects requires a loop and the startup context.
async::Loop loop(&kAsyncLoopConfigAttachToThread);
auto component_context = sys::ComponentContext::Create();
// Legacy work required to expose an object tree over FIDL.
auto root = component::ObjectDir::Make("root");
fidl::BindingSet<fuchsia::inspect::Inspect> inspect_bindings_;
component_context->outgoing()->GetOrCreateDirectory("objects")->AddEntry(
fuchsia::inspect::Inspect::Name_,
std::make_unique<vfs::Service>(
inspect_bindings_.GetHandler(root.object().get())));
auto root_object_fidl = inspect::Object(root);
auto inspector =
inspect::ComponentInspector::Initialize(component_context.get());
auto& root_object_vmo = inspector->root_tree()->GetRoot();
// Storage for the two different table implementations, for ensuring they are
// the same.
std::vector<Table> tables;
const int row_count = atoi(rows.c_str());
const int col_count = atoi(columns.c_str());
std::vector<
std::variant<inspect::IntArray, inspect::UIntArray, inspect::DoubleArray>>
arrays;
std::vector<std::variant<inspect::LinearIntHistogramMetric,
inspect::LinearUIntHistogramMetric,
inspect::LinearDoubleHistogramMetric,
inspect::ExponentialIntHistogramMetric,
inspect::ExponentialUIntHistogramMetric,
inspect::ExponentialDoubleHistogramMetric>>
histograms;
for (auto* root :
std::vector<inspect::Object*>({&root_object_fidl, &root_object_vmo})) {
ResetUniqueNames();
tables.emplace_back(row_count, col_count,
root->CreateChild(UniqueName("table")));
{
auto array = root->CreateIntArray(UniqueName("array"), 3);
array.Set(0, 1);
array.Add(1, 10);
array.Subtract(2, 3);
arrays.emplace_back(std::move(array));
}
{
auto array = root->CreateUIntArray(UniqueName("array"), 3);
array.Set(0, 1);
array.Add(1, 10);
array.Set(2, 3);
array.Subtract(2, 1);
arrays.emplace_back(std::move(array));
}
{
auto array = root->CreateDoubleArray(UniqueName("array"), 3);
array.Set(0, 0.25);
array.Add(1, 1.25);
array.Subtract(2, 0.75);
arrays.emplace_back(std::move(array));
}
histograms.emplace_back(
PopulatedHistogram(root->CreateLinearIntHistogramMetric(
UniqueName("histogram"), -10, 5, 3),
-20, 1, 40));
histograms.emplace_back(PopulatedHistogram(
root->CreateLinearUIntHistogramMetric(UniqueName("histogram"), 5, 5, 3),
0, 1, 40));
histograms.emplace_back(
PopulatedHistogram(root->CreateLinearDoubleHistogramMetric(
UniqueName("histogram"), 0, .5, 3),
-1.0, .1, 40.0));
histograms.emplace_back(
PopulatedHistogram(root->CreateExponentialIntHistogramMetric(
UniqueName("histogram"), -10, 5, 2, 3),
-20, 1, 40));
histograms.emplace_back(
PopulatedHistogram(root->CreateExponentialUIntHistogramMetric(
UniqueName("histogram"), 1, 1, 2, 3),
0, 1, 40));
histograms.emplace_back(
PopulatedHistogram(root->CreateExponentialDoubleHistogramMetric(
UniqueName("histogram"), 0, 1.25, 3, 3),
-1.0, .1, 40.0));
}
loop.Run();
return 0;
}