Skip to content

Commit

Permalink
Introduce a ValueContext to use for rendering complex map values afte…
Browse files Browse the repository at this point in the history
…r having emitted the key.

Signed-off-by: Joshua Marantz <[email protected]>
  • Loading branch information
jmarantz committed Aug 18, 2023
1 parent 0044126 commit 7d985de
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 44 deletions.
10 changes: 6 additions & 4 deletions source/common/json/json_streamer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,21 @@ void Streamer::Map::newEntry() {
}
}

void Streamer::Map::newKey(absl::string_view name) {
Streamer::Map::ValuePtr Streamer::Map::newKey(absl::string_view name) {
newEntry();
streamer_.addFragments({"\"", name, "\":"});
ASSERT(!expecting_value_);
expecting_value_ = true;
return std::make_unique<Value>(*this);
}

void Streamer::Map::newSanitizedValue(absl::string_view value) {
/*void Streamer::Map::newSanitizedValue(absl::string_view value) {
ASSERT(expecting_value_);
streamer_.addSanitized(value);
expecting_value_ = false;
}
}*/

void Streamer::Map::endValue() { expecting_value_ = false; }
// void Streamer::Map::endValue() { expecting_value_ = false; }

void Streamer::Map::newEntries(const Entries& entries) {
for (const NameValue& entry : entries) {
Expand Down
12 changes: 10 additions & 2 deletions source/common/json/json_streamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,20 @@ class Streamer {
using NameValue = std::pair<const absl::string_view, const absl::string_view>;
using Entries = absl::Span<const NameValue>;

struct Value {
Value(Map& map) : map_(map) {}
~Value() { map_.expecting_value_ = false; }
void addSanitized(absl::string_view value) { map_.streamer_.addSanitized(value); }
Map& map_;
};
using ValuePtr = std::unique_ptr<Value>;

Map(Streamer& streamer) : Level(streamer, "{", "}") {}
void newKey(absl::string_view name);
ValuePtr newKey(absl::string_view name);
void newEntries(const Entries& entries);
virtual void newEntry() override;
void newSanitizedValue(absl::string_view value);
void endValue();
// void endValue();

bool expecting_value_{false};
};
Expand Down
97 changes: 59 additions & 38 deletions source/server/admin/stats_render.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ StatsJsonRender::StatsJsonRender(Http::ResponseHeaderMap& response_headers,
// We don't create a JSON data model for the stats output, as that makes
// streaming difficult. Instead we emit the preamble in the constructor here,
// and create json models for each stats entry.
json_stats_map_->newKey("stats");
stats_value_context_ = json_stats_map_->newKey("stats");
json_stats_array_ = json_streamer_.newArray();
}

Expand Down Expand Up @@ -224,25 +224,36 @@ void StatsJsonRender::renderHistogramStart() {
histograms_initialized_ = true;
json_stats_array_->newEntry();
json_histogram_map1_ = json_streamer_.newMap();
json_histogram_map1_->newKey("histograms");
Json::Streamer::Map::ValuePtr hist_value_context = json_histogram_map1_->newKey("histograms");

switch (histogram_buckets_mode_) {
case Utility::HistogramBucketsMode::Detailed:
json_histogram_map2_ = json_streamer_.newMap();
json_histogram_map2_->newKey("supported_percentiles");
populateSupportedPercentiles();
json_histogram_map2_->endValue();
json_histogram_map2_->newKey("details");
json_histogram_array_ = json_streamer_.newArray();
json_histogram_map2_->endValue();
{
Json::Streamer::Map::ValuePtr value_context =
json_histogram_map2_->newKey("supported_percentiles");
populateSupportedPercentiles();
// json_histogram_map2_->endValue();
}
{
Json::Streamer::Map::ValuePtr value_context = json_histogram_map2_->newKey("details");
json_histogram_array_ = json_streamer_.newArray();
// json_histogram_map2_->endValue();
}
break;
case Utility::HistogramBucketsMode::NoBuckets:
json_histogram_map2_ = json_streamer_.newMap();
json_histogram_map2_->newKey("supported_quantiles");
populateSupportedPercentiles();
json_histogram_map2_->endValue();
json_histogram_map2_->newKey("computed_quantiles");
json_histogram_array_ = json_streamer_.newArray();
{
Json::Streamer::Map::ValuePtr value_context =
json_histogram_map2_->newKey("supported_quantiles");
populateSupportedPercentiles();
// json_histogram_map2_->endValue();
}
{
Json::Streamer::Map::ValuePtr value_context =
json_histogram_map2_->newKey("computed_quantiles");
json_histogram_array_ = json_streamer_.newArray();
}
break;
case Utility::HistogramBucketsMode::Cumulative:
case Utility::HistogramBucketsMode::Disjoint:
Expand All @@ -258,16 +269,20 @@ void StatsJsonRender::generateHistogramDetail(const std::string& name,
Json::Streamer::Map& map = json_streamer_.newMap();
map.newEntries({{"name", absl::StrCat("\"", Json::sanitize(name_buffer_, name), "\"")}});

map.newKey("totals");
populateBucketsVerbose(histogram.detailedTotalBuckets());
map.endValue();
map.newKey("intervals");
populateBucketsVerbose(histogram.detailedIntervalBuckets());
map.endValue();

map.newKey("percentiles");
populatePercentiles(histogram);
map.endValue();
{
Json::Streamer::Map::ValuePtr value_context = map.newKey("totals");
populateBucketsVerbose(histogram.detailedTotalBuckets());
}
{
Json::Streamer::Map::ValuePtr value_context = map.newKey("intervals");
populateBucketsVerbose(histogram.detailedIntervalBuckets());
// map.endValue();
}
{
Json::Streamer::Map::ValuePtr value_context = map.newKey("percentiles");
populatePercentiles(histogram);
// map.endValue();
}
}

void StatsJsonRender::populateBucketsTerse(
Expand Down Expand Up @@ -298,6 +313,7 @@ void StatsJsonRender::populateBucketsVerbose(
// Since histograms are buffered (see above), the finalize() method generates
// all of them.
void StatsJsonRender::finalize(Buffer::Instance& response) {
stats_value_context_.reset();
json_streamer_.clear();
drainIfNeeded(response);
}
Expand All @@ -318,22 +334,27 @@ void StatsJsonRender::collectBuckets(const std::string& name,
std::min({interval_buckets.size(), cumulative_buckets.size(), supported_buckets.size()});

Json::Streamer::Map& map = json_streamer_.newMap();
map.newKey("name");
map.newSanitizedValue(name);
map.newKey("buckets");
Json::Streamer::Array& buckets = json_streamer_.newArray();
for (uint32_t i = 0; i < min_size; ++i) {
buckets.newEntry();
Json::Streamer::Map& bucket_map = json_streamer_.newMap();
// using NameValue = Json::Streamer::Map::NameValue;
bucket_map.newEntries({{"upper_bound", Json::Streamer::number(supported_buckets[i])},
{"interval", Json::Streamer::number(interval_buckets[i])},
{"cumulative", Json::Streamer::number(cumulative_buckets[i])}});

json_streamer_.pop(bucket_map);
{
Json::Streamer::Map::ValuePtr value_context = map.newKey("name");
value_context->addSanitized(name);
}
// map.newSanitizedValue(name);
{
Json::Streamer::Map::ValuePtr value_context = map.newKey("buckets");
Json::Streamer::Array& buckets = json_streamer_.newArray();
for (uint32_t i = 0; i < min_size; ++i) {
buckets.newEntry();
Json::Streamer::Map& bucket_map = json_streamer_.newMap();
// using NameValue = Json::Streamer::Map::NameValue;
bucket_map.newEntries({{"upper_bound", Json::Streamer::number(supported_buckets[i])},
{"interval", Json::Streamer::number(interval_buckets[i])},
{"cumulative", Json::Streamer::number(cumulative_buckets[i])}});

json_streamer_.pop(bucket_map);
}
// map.endValue();
json_streamer_.pop(buckets);
}
map.endValue();
json_streamer_.pop(buckets);
json_streamer_.pop(map);
}

Expand Down
1 change: 1 addition & 0 deletions source/server/admin/stats_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class StatsJsonRender : public StatsRender {
bool histograms_initialized_{false};
Json::Streamer json_streamer_;
OptRef<Json::Streamer::Map> json_stats_map_;
Json::Streamer::Map::ValuePtr stats_value_context_;
OptRef<Json::Streamer::Array> json_stats_array_;
OptRef<Json::Streamer::Map> json_histogram_map1_;
OptRef<Json::Streamer::Map> json_histogram_map2_;
Expand Down

0 comments on commit 7d985de

Please sign in to comment.