Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
832ec74
initial commit; several candidate call-sites not covered yet.
jmarantz Apr 10, 2020
794ae83
put common testname in anon namespace.
jmarantz Apr 10, 2020
7bd3aba
format
jmarantz Apr 10, 2020
5e1c309
rename test-class as it maybe is causing some kind of coverage-test c…
jmarantz Apr 10, 2020
84b223b
Merge branch 'master' into counter-from-vector
jmarantz Apr 17, 2020
6d9aaa7
use new stats utility for zookeeper.
jmarantz Apr 21, 2020
2e3a35d
mongo and zookeeper
jmarantz Apr 21, 2020
e57c493
fault filter, and zookeeper cleanup
jmarantz Apr 21, 2020
90fd639
Require an explicit 'Dynamic' type annotation for dynamic strings pas…
jmarantz Apr 21, 2020
91ff5ac
dynamo
jmarantz Apr 21, 2020
e04076e
Merge branch 'master' into counter-from-vector
jmarantz Apr 21, 2020
85b57ed
add ScopeSharedImpl as an alternative leaner API to Utility::*FromEle…
jmarantz Apr 21, 2020
558fd2e
Revert "add ScopeSharedImpl as an alternative leaner API to Utility::…
jmarantz Apr 22, 2020
fb31f20
name cleanups.
jmarantz Apr 22, 2020
c285307
format, and convert grpc to new pattern.
jmarantz Apr 22, 2020
e418417
add variants that accept only StatName, but are a bit leaner in imple…
jmarantz Apr 23, 2020
ae315a7
more cleanups and add support for TextReadout
jmarantz Apr 23, 2020
5e9ccce
Merge branch 'master' into counter-from-vector
jmarantz Apr 23, 2020
3c4df6e
Merge branch 'master' into counter-from-vector
jmarantz Apr 24, 2020
8aa6462
review comments
jmarantz Apr 24, 2020
ab073ff
use "using" rather than explicit ctor.
jmarantz Apr 24, 2020
d5adafb
Use inlined vectors for Stats::Utility::ElementVec
jmarantz Apr 24, 2020
ea243dd
Merge branch 'master' into counter-from-vector
jmarantz Apr 24, 2020
969c26a
Go back to using a constructor rather than inheriting the base class'…
jmarantz Apr 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions source/common/grpc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ envoy_cc_library(
"//include/envoy/stats:stats_interface",
"//source/common/common:hash_lib",
"//source/common/stats:symbol_table_lib",
"//source/common/stats:utility_lib",
],
)

Expand Down
103 changes: 28 additions & 75 deletions source/common/grpc/context_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,29 @@
#include <string>

#include "common/grpc/common.h"
#include "common/stats/utility.h"

namespace Envoy {
namespace Grpc {

ContextImpl::ContextImpl(Stats::SymbolTable& symbol_table)
: symbol_table_(symbol_table), stat_name_pool_(symbol_table),
grpc_(stat_name_pool_.add("grpc")), grpc_web_(stat_name_pool_.add("grpc-web")),
success_(stat_name_pool_.add("success")), failure_(stat_name_pool_.add("failure")),
total_(stat_name_pool_.add("total")), zero_(stat_name_pool_.add("0")),
: stat_name_pool_(symbol_table), grpc_(stat_name_pool_.add("grpc")),
grpc_web_(stat_name_pool_.add("grpc-web")), success_(stat_name_pool_.add("success")),
failure_(stat_name_pool_.add("failure")), total_(stat_name_pool_.add("total")),
zero_(stat_name_pool_.add("0")),
request_message_count_(stat_name_pool_.add("request_message_count")),
response_message_count_(stat_name_pool_.add("response_message_count")),
upstream_rq_time_(stat_name_pool_.add("upstream_rq_time")), stat_names_(symbol_table) {}

// Makes a stat name from a string, if we don't already have one for it.
// This always takes a lock on mutex_, and if we haven't seen the name
// before, it also takes a lock on the symbol table.
//
// TODO(jmarantz): See https://github.com/envoyproxy/envoy/pull/7008 for
// a lock-free approach to creating dynamic stat-names based on requests.
Stats::StatName ContextImpl::makeDynamicStatName(absl::string_view name) {
Thread::LockGuard lock(mutex_);
auto iter = stat_name_map_.find(name);
if (iter != stat_name_map_.end()) {
return iter->second;
}
const Stats::StatName stat_name = stat_name_pool_.add(name);
stat_name_map_[std::string(name)] = stat_name;
return stat_name;
}

// Gets the stat prefix and underlying storage, depending on whether request_names is empty
std::pair<Stats::StatName, Stats::SymbolTable::StoragePtr>
ContextImpl::getPrefix(Protocol protocol, const absl::optional<RequestStatNames>& request_names) {
Stats::ElementVec ContextImpl::statElements(Protocol protocol,
const absl::optional<RequestStatNames>& request_names,
Stats::Element suffix) {
const Stats::StatName protocolName = protocolStatName(protocol);
if (request_names) {
Stats::SymbolTable::StoragePtr prefix_storage =
symbol_table_.join({protocolName, request_names->service_, request_names->method_});
Stats::StatName prefix = Stats::StatName(prefix_storage.get());
return {prefix, std::move(prefix_storage)};
} else {
return {protocolName, nullptr};
return Stats::ElementVec{protocolName, request_names->service_, request_names->method_, suffix};
}
return Stats::ElementVec{protocolName, suffix};
}

void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol protocol,
Expand All @@ -57,28 +38,20 @@ void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol prot

absl::string_view status_str = grpc_status->value().getStringView();
auto iter = stat_names_.status_names_.find(status_str);
const Stats::StatName status_stat_name =
(iter != stat_names_.status_names_.end()) ? iter->second : makeDynamicStatName(status_str);
const Stats::SymbolTable::StoragePtr stat_name_storage =
request_names ? symbol_table_.join({protocolStatName(protocol), request_names->service_,
request_names->method_, status_stat_name})
: symbol_table_.join({protocolStatName(protocol), status_stat_name});

cluster.statsScope().counterFromStatName(Stats::StatName(stat_name_storage.get())).inc();
Stats::ElementVec elements =
statElements(protocol, request_names,
(iter != stat_names_.status_names_.end()) ? Stats::Element(iter->second)
: Stats::DynamicName(status_str));
Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
chargeStat(cluster, protocol, request_names, (status_str == "0"));
}

void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster, Protocol protocol,
const absl::optional<RequestStatNames>& request_names, bool success) {
auto prefix_and_storage = getPrefix(protocol, request_names);
Stats::StatName prefix = prefix_and_storage.first;

const Stats::SymbolTable::StoragePtr status =
symbol_table_.join({prefix, successStatName(success)});
const Stats::SymbolTable::StoragePtr total = symbol_table_.join({prefix, total_});

cluster.statsScope().counterFromStatName(Stats::StatName(status.get())).inc();
cluster.statsScope().counterFromStatName(Stats::StatName(total.get())).inc();
Stats::ElementVec elements = statElements(protocol, request_names, successStatName(success));
Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
elements.back() = total_;
Stats::Utility::counterFromElements(cluster.statsScope(), elements).inc();
}

void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster,
Expand All @@ -89,43 +62,23 @@ void ContextImpl::chargeStat(const Upstream::ClusterInfo& cluster,
void ContextImpl::chargeRequestMessageStat(const Upstream::ClusterInfo& cluster,
const absl::optional<RequestStatNames>& request_names,
uint64_t amount) {
auto prefix_and_storage = getPrefix(Protocol::Grpc, request_names);
Stats::StatName prefix = prefix_and_storage.first;

const Stats::SymbolTable::StoragePtr request_message_count =
symbol_table_.join({prefix, request_message_count_});

cluster.statsScope()
.counterFromStatName(Stats::StatName(request_message_count.get()))
.add(amount);
Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, request_message_count_);
Stats::Utility::counterFromElements(cluster.statsScope(), elements).add(amount);
}

void ContextImpl::chargeResponseMessageStat(const Upstream::ClusterInfo& cluster,
const absl::optional<RequestStatNames>& request_names,
uint64_t amount) {
auto prefix_and_storage = getPrefix(Protocol::Grpc, request_names);
Stats::StatName prefix = prefix_and_storage.first;

const Stats::SymbolTable::StoragePtr response_message_count =
symbol_table_.join({prefix, response_message_count_});

cluster.statsScope()
.counterFromStatName(Stats::StatName(response_message_count.get()))
.add(amount);
Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, response_message_count_);
Stats::Utility::counterFromElements(cluster.statsScope(), elements).add(amount);
}

void ContextImpl::chargeUpstreamStat(const Upstream::ClusterInfo& cluster,
const absl::optional<RequestStatNames>& request_names,
std::chrono::milliseconds duration) {
auto prefix_and_storage = getPrefix(Protocol::Grpc, request_names);
Stats::StatName prefix = prefix_and_storage.first;

const Stats::SymbolTable::StoragePtr upstream_rq_time =
symbol_table_.join({prefix, upstream_rq_time_});

cluster.statsScope()
.histogramFromStatName(Stats::StatName(upstream_rq_time.get()),
Stats::Histogram::Unit::Milliseconds)
Stats::ElementVec elements = statElements(Protocol::Grpc, request_names, upstream_rq_time_);
Stats::Utility::histogramFromElements(cluster.statsScope(), elements,
Stats::Histogram::Unit::Milliseconds)
.recordValue(duration.count());
}

Expand All @@ -136,8 +89,8 @@ ContextImpl::resolveDynamicServiceAndMethod(const Http::HeaderEntry* path) {
return {};
}

const Stats::StatName service = makeDynamicStatName(request_names->service_);
const Stats::StatName method = makeDynamicStatName(request_names->method_);
Stats::Element service = Stats::DynamicName(request_names->service_);
Stats::Element method = Stats::DynamicName(request_names->method_);
return RequestStatNames{service, method};
}

Expand Down
29 changes: 9 additions & 20 deletions source/common/grpc/context_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
#include "common/common/hash.h"
#include "common/grpc/stat_names.h"
#include "common/stats/symbol_table_impl.h"
#include "common/stats/utility.h"

#include "absl/types/optional.h"

namespace Envoy {
namespace Grpc {

struct Context::RequestStatNames {
Stats::StatName service_; // supplies the service name.
Stats::StatName method_; // supplies the method name.
Stats::Element service_; // supplies the service name.
Stats::Element method_; // supplies the method name.
};

class ContextImpl : public Context {
Expand Down Expand Up @@ -59,25 +60,13 @@ class ContextImpl : public Context {
StatNames& statNames() override { return stat_names_; }

private:
// Makes a stat name from a string, if we don't already have one for it.
// This always takes a lock on mutex_, and if we haven't seen the name
// before, it also takes a lock on the symbol table.
//
// TODO(jmarantz): See https://github.com/envoyproxy/envoy/pull/7008 for
// a lock-free approach to creating dynamic stat-names based on requests.
Stats::StatName makeDynamicStatName(absl::string_view name);

// Gets the stat prefix and underlying storage, depending on whether request_names is empty
// or not.
// Prefix will be "<protocol>" if request_names is empty, or
// "<protocol>.<service>.<method>" if it is not empty.
std::pair<Stats::StatName, Stats::SymbolTable::StoragePtr>
getPrefix(Protocol protocol, const absl::optional<RequestStatNames>& request_names);
// Creates an array of stat-name elements, comprising the protocol, optional
// service and method, and a suffix.
Stats::ElementVec statElements(Protocol protocol,
const absl::optional<RequestStatNames>& request_names,
Stats::Element suffix);

Stats::SymbolTable& symbol_table_;
mutable Thread::MutexBasicLockable mutex_;
Stats::StatNamePool stat_name_pool_ ABSL_GUARDED_BY(mutex_);
StringMap<Stats::StatName> stat_name_map_ ABSL_GUARDED_BY(mutex_);
Stats::StatNamePool stat_name_pool_;
const Stats::StatName grpc_;
const Stats::StatName grpc_web_;
const Stats::StatName success_;
Expand Down
1 change: 1 addition & 0 deletions source/common/http/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ envoy_cc_library(
"//include/envoy/stats:stats_macros",
"//include/envoy/stats:timespan_interface",
"//source/common/stats:symbol_table_lib",
"//source/common/stats:utility_lib",
],
)

Expand Down
20 changes: 9 additions & 11 deletions source/common/http/user_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "common/http/headers.h"
#include "common/stats/symbol_table_impl.h"
#include "common/stats/utility.h"

namespace Envoy {
namespace Http {
Expand All @@ -30,17 +31,14 @@ void UserAgent::completeConnectionLength(Stats::Timespan& span) {

UserAgentStats::UserAgentStats(Stats::StatName prefix, Stats::StatName device, Stats::Scope& scope,
const UserAgentContext& context)
: downstream_cx_total_(scope.counterFromStatName(Stats::StatName(
context.symbol_table_.join({prefix, device, context.downstream_cx_total_}).get()))),
downstream_cx_destroy_remote_active_rq_(scope.counterFromStatName(Stats::StatName(
context.symbol_table_
.join({prefix, device, context.downstream_cx_destroy_remote_active_rq_})
.get()))),
downstream_rq_total_(scope.counterFromStatName(Stats::StatName(
context.symbol_table_.join({prefix, device, context.downstream_rq_total_}).get()))),
downstream_cx_length_ms_(scope.histogramFromStatName(
Stats::StatName(
context.symbol_table_.join({prefix, device, context.downstream_cx_length_ms_}).get()),
: downstream_cx_total_(Stats::Utility::counterFromElements(
scope, {prefix, device, context.downstream_cx_total_})),
downstream_cx_destroy_remote_active_rq_(Stats::Utility::counterFromElements(
scope, {prefix, device, context.downstream_cx_destroy_remote_active_rq_})),
downstream_rq_total_(Stats::Utility::counterFromElements(
scope, {prefix, device, context.downstream_rq_total_})),
downstream_cx_length_ms_(Stats::Utility::histogramFromElements(
scope, {prefix, device, context.downstream_cx_length_ms_},
Stats::Histogram::Unit::Milliseconds)) {
downstream_cx_total_.inc();
downstream_rq_total_.inc();
Expand Down
83 changes: 83 additions & 0 deletions source/common/stats/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <string>

#include "absl/strings/match.h"
#include "absl/types/optional.h"

namespace Envoy {
namespace Stats {
Expand Down Expand Up @@ -34,5 +35,87 @@ absl::optional<StatName> Utility::findTag(const Metric& metric, StatName find_ta
return value;
}

namespace {

// Helper class for the three Utility::*FromElements implementations to build up
// a joined StatName from a mix of StatName and string_view.
struct ElementVisitor {
ElementVisitor(SymbolTable& symbol_table, const ElementVec& elements)
: symbol_table_(symbol_table), pool_(symbol_table) {
stat_names_.resize(elements.size());
for (const Element& element : elements) {
absl::visit(*this, element);
}
joined_ = symbol_table_.join(stat_names_);
}

// Overloads provides for absl::visit to call.
void operator()(StatName stat_name) { stat_names_.push_back(stat_name); }
void operator()(absl::string_view name) { stat_names_.push_back(pool_.add(name)); }

/**
* @return the StatName constructed by joining the elements.
*/
StatName statName() { return StatName(joined_.get()); }

SymbolTable& symbol_table_;
StatNameVec stat_names_;
StatNameDynamicPool pool_;
SymbolTable::StoragePtr joined_;
};

} // namespace

Counter& Utility::counterFromElements(Scope& scope, const ElementVec& elements,
StatNameTagVectorOptConstRef tags) {
ElementVisitor visitor(scope.symbolTable(), elements);
return scope.counterFromStatNameWithTags(visitor.statName(), tags);
}

Counter& Utility::counterFromStatNames(Scope& scope, const StatNameVec& elements,
StatNameTagVectorOptConstRef tags) {
SymbolTable::StoragePtr joined = scope.symbolTable().join(elements);
return scope.counterFromStatNameWithTags(StatName(joined.get()), tags);
}

Gauge& Utility::gaugeFromElements(Scope& scope, const ElementVec& elements,
Gauge::ImportMode import_mode,
StatNameTagVectorOptConstRef tags) {
ElementVisitor visitor(scope.symbolTable(), elements);
return scope.gaugeFromStatNameWithTags(visitor.statName(), tags, import_mode);
}

Gauge& Utility::gaugeFromStatNames(Scope& scope, const StatNameVec& elements,
Gauge::ImportMode import_mode,
StatNameTagVectorOptConstRef tags) {
SymbolTable::StoragePtr joined = scope.symbolTable().join(elements);
return scope.gaugeFromStatNameWithTags(StatName(joined.get()), tags, import_mode);
}

Histogram& Utility::histogramFromElements(Scope& scope, const ElementVec& elements,
Histogram::Unit unit, StatNameTagVectorOptConstRef tags) {
ElementVisitor visitor(scope.symbolTable(), elements);
return scope.histogramFromStatNameWithTags(visitor.statName(), tags, unit);
}

Histogram& Utility::histogramFromStatNames(Scope& scope, const StatNameVec& elements,
Histogram::Unit unit,
StatNameTagVectorOptConstRef tags) {
SymbolTable::StoragePtr joined = scope.symbolTable().join(elements);
return scope.histogramFromStatNameWithTags(StatName(joined.get()), tags, unit);
}

TextReadout& Utility::textReadoutFromElements(Scope& scope, const ElementVec& elements,
StatNameTagVectorOptConstRef tags) {
ElementVisitor visitor(scope.symbolTable(), elements);
return scope.textReadoutFromStatNameWithTags(visitor.statName(), tags);
}

TextReadout& Utility::textReadoutFromStatNames(Scope& scope, const StatNameVec& elements,
StatNameTagVectorOptConstRef tags) {
SymbolTable::StoragePtr joined = scope.symbolTable().join(elements);
return scope.textReadoutFromStatNameWithTags(StatName(joined.get()), tags);
}

} // namespace Stats
} // namespace Envoy
Loading