Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adaptive load session spec proto helpers #508

Merged
merged 52 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
8ea442d
Merge pull request #5 from envoyproxy/master
eric846 Jun 1, 2020
5ac755a
Merge pull request #6 from envoyproxy/master
eric846 Jun 28, 2020
b8c25a5
Merge pull request #7 from envoyproxy/master
eric846 Jul 7, 2020
1c19c68
initial commit
eric846 Jul 9, 2020
7050686
fix comments
eric846 Jul 9, 2020
0776563
fix format
eric846 Jul 9, 2020
16fd8f6
rename adaptive_rps to adaptive_load
eric846 Jul 10, 2020
c383010
add field_selector in example
eric846 Jul 10, 2020
6e1a483
fix example comment
eric846 Jul 10, 2020
4ef1140
fix format
eric846 Jul 10, 2020
4111bf4
add support for fault injection headers
eric846 Jul 10, 2020
871a959
replace linear and binary search with exponential search
eric846 Jul 10, 2020
1fd77c1
add InputVariableSetter mechanism
eric846 Jul 11, 2020
edc36b2
add input variable setter to build file
eric846 Jul 11, 2020
4d0364e
fix syntax errors
eric846 Jul 11, 2020
aed6d94
rename samples/adaptive_rps
eric846 Jul 11, 2020
d9ae87d
improve comments, change step controller initial value from int64 to …
eric846 Jul 12, 2020
a05a6f5
add proto validation rules, fix comments, make rps the default input_…
eric846 Jul 13, 2020
8cd4d21
fix comment wording
eric846 Jul 13, 2020
d814a96
simplify protos, add defaults, specify required or optional
eric846 Jul 14, 2020
5f5a885
add missing newline
eric846 Jul 14, 2020
7e20a78
Kick CI
eric846 Jul 14, 2020
9048267
simplify protos
eric846 Jul 15, 2020
306c0ec
fix format
eric846 Jul 15, 2020
d33f543
fix some optional field comments and rules
eric846 Jul 15, 2020
442cca9
Merge pull request #10 from envoyproxy/master
eric846 Jul 16, 2020
677b783
add Nighthawk status field in BenchmarkResult as nested nighthawk.cli…
eric846 Jul 19, 2020
cefb366
switch to standard Envoy plugin config proto, add prefix to internal …
eric846 Jul 22, 2020
f3684df
Merge remote-tracking branch 'upstream/master' into adaptive-rps-protos2
eric846 Jul 22, 2020
5463051
create headers
eric846 Jul 22, 2020
46e0e25
fix format
eric846 Jul 22, 2020
f634642
use docstring format
eric846 Jul 22, 2020
3c39faa
fix typos in comments
eric846 Jul 23, 2020
b9c8f2b
split build target, get rid of ostream, change InputValueSetter to us…
eric846 Jul 24, 2020
5fc4db4
remove nested namespace, remove redundant _include in target names
eric846 Jul 26, 2020
64e7852
merge from upstream
eric846 Jul 29, 2020
12807f1
Merge remote-tracking branch 'upstream/master' into adaptive-rps-headers
eric846 Jul 29, 2020
e8e960f
merge from upstream
eric846 Aug 27, 2020
6306b4e
Merge remote-tracking branch 'upstream/master' into master2
eric846 Aug 27, 2020
1ece783
Merge remote-tracking branch 'upstream/master' into master2
eric846 Aug 28, 2020
70705e9
Merge remote-tracking branch 'upstream/master' into master2
eric846 Aug 31, 2020
e576bc1
Merge remote-tracking branch 'upstream/master' into master2
eric846 Sep 1, 2020
1fca528
Merge remote-tracking branch 'upstream/master' into master2
eric846 Sep 3, 2020
8eae526
initial commit - session spec proto helper and FakeMetricsPlugin helper
eric846 Sep 3, 2020
a10b625
rename SetDefaults
eric846 Sep 3, 2020
f2dccb2
fix clang-tidy
eric846 Sep 3, 2020
ed32856
Merge remote-tracking branch 'upstream/master' into master2
eric846 Sep 3, 2020
eecf00d
Merge remote-tracking branch 'upstream/master' into master2
eric846 Sep 8, 2020
ce68373
Merge branch 'master2' into adaptive-rps-spec-validation
eric846 Sep 8, 2020
07493ae
remove accidental comment
eric846 Sep 8, 2020
13179fb
Merge remote-tracking branch 'upstream/master' into master2
eric846 Sep 10, 2020
6bcae4d
Merge branch 'master2' into adaptive-rps-spec-validation
eric846 Sep 10, 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
13 changes: 13 additions & 0 deletions include/nighthawk/adaptive_load/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ envoy_basic_cc_library(
],
)

envoy_basic_cc_library(
name = "session_spec_proto_helper",
hdrs = [
"session_spec_proto_helper.h",
],
include_prefix = "nighthawk/adaptive_load",
deps = [
"//api/adaptive_load:adaptive_load_proto_cc_proto",
"@com_google_absl//absl/status",
"@envoy//include/envoy/common:base_includes",
],
)

envoy_basic_cc_library(
name = "step_controller",
hdrs = [
Expand Down
43 changes: 43 additions & 0 deletions include/nighthawk/adaptive_load/session_spec_proto_helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include "envoy/common/pure.h"

#include "api/adaptive_load/adaptive_load.pb.h"

#include "absl/status/status.h"

namespace Nighthawk {

/**
* Utilities for setting default values and validating user settings in the main
* AdaptiveLoadSessionSpec proto.
*/
class AdaptiveLoadSessionSpecProtoHelper {
public:
virtual ~AdaptiveLoadSessionSpecProtoHelper() = default;

/**
* Returns a copy of the input spec with default values inserted. Avoids overriding pre-set values
* in the original spec.
*
* @param spec Valid adaptive load session spec.
*
* @return Adaptive load session spec with default values inserted.
*/
virtual nighthawk::adaptive_load::AdaptiveLoadSessionSpec
SetSessionSpecDefaults(nighthawk::adaptive_load::AdaptiveLoadSessionSpec spec) PURE;

/**
* Checks whether a session spec is valid: No forbidden fields in Nighthawk traffic spec; no bad
* plugin references or bad plugin configurations (step controller, metric, scoring function); no
* nonexistent metric names. Reports all errors in one pass.
*
* @param spec A potentially invalid adaptive load session spec.
*
* @return Status OK if no problems were found, or InvalidArgument with all errors.
*/
virtual absl::Status
CheckSessionSpec(const nighthawk::adaptive_load::AdaptiveLoadSessionSpec& spec) PURE;
};

} // namespace Nighthawk
22 changes: 22 additions & 0 deletions source/adaptive_load/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,28 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "session_spec_proto_helper_impl",
srcs = [
"session_spec_proto_helper_impl.cc",
],
hdrs = [
"session_spec_proto_helper_impl.h",
],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
":metrics_plugin_impl",
":plugin_loader",
"//include/nighthawk/adaptive_load:metrics_plugin",
"//include/nighthawk/adaptive_load:scoring_function",
"//include/nighthawk/adaptive_load:session_spec_proto_helper",
"//include/nighthawk/adaptive_load:step_controller",
"@envoy//source/common/config:utility_lib_with_external_headers",
"@envoy//source/common/protobuf:protobuf_with_external_headers",
],
)

envoy_cc_library(
name = "step_controller_impl",
srcs = [
Expand Down
119 changes: 119 additions & 0 deletions source/adaptive_load/session_spec_proto_helper_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include "adaptive_load/session_spec_proto_helper_impl.h"

#include "nighthawk/adaptive_load/metrics_plugin.h"
#include "nighthawk/adaptive_load/step_controller.h"

#include "api/adaptive_load/adaptive_load.pb.h"
#include "api/adaptive_load/metric_spec.pb.h"

#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "adaptive_load/metrics_plugin_impl.h"
#include "adaptive_load/plugin_loader.h"

namespace Nighthawk {

nighthawk::adaptive_load::AdaptiveLoadSessionSpec
AdaptiveLoadSessionSpecProtoHelperImpl::SetSessionSpecDefaults(
nighthawk::adaptive_load::AdaptiveLoadSessionSpec spec) {
if (!spec.nighthawk_traffic_template().has_open_loop()) {
spec.mutable_nighthawk_traffic_template()->mutable_open_loop()->set_value(true);
}
if (!spec.has_measuring_period()) {
spec.mutable_measuring_period()->set_seconds(10);
}
if (!spec.has_convergence_deadline()) {
spec.mutable_convergence_deadline()->set_seconds(300);
}
if (!spec.has_testing_stage_duration()) {
spec.mutable_testing_stage_duration()->set_seconds(30);
}
for (nighthawk::adaptive_load::MetricSpecWithThreshold& threshold :
*spec.mutable_metric_thresholds()) {
if (threshold.metric_spec().metrics_plugin_name().empty()) {
threshold.mutable_metric_spec()->set_metrics_plugin_name("nighthawk.builtin");
}
if (!threshold.threshold_spec().has_weight()) {
threshold.mutable_threshold_spec()->mutable_weight()->set_value(1.0);
}
}
for (nighthawk::adaptive_load::MetricSpec& metric_spec :
*spec.mutable_informational_metric_specs()) {
if (metric_spec.metrics_plugin_name().empty()) {
metric_spec.set_metrics_plugin_name("nighthawk.builtin");
}
}
return spec;
}

absl::Status AdaptiveLoadSessionSpecProtoHelperImpl::CheckSessionSpec(
const nighthawk::adaptive_load::AdaptiveLoadSessionSpec& spec) {
std::vector<std::string> errors;
if (spec.nighthawk_traffic_template().has_duration()) {
errors.emplace_back(
"nighthawk_traffic_template should not have |duration| set. Set |measuring_period| "
"and |testing_stage_duration| in the AdaptiveLoadSessionSpec proto instead.");
}
absl::flat_hash_map<std::string, MetricsPluginPtr> plugin_from_name;
std::vector<std::string> plugin_names = {"nighthawk.builtin"};
plugin_from_name["nighthawk.builtin"] =
std::make_unique<NighthawkStatsEmulatedMetricsPlugin>(nighthawk::client::Output());
for (const envoy::config::core::v3::TypedExtensionConfig& config :
spec.metrics_plugin_configs()) {
plugin_names.push_back(config.name());
absl::StatusOr<MetricsPluginPtr> metrics_plugin_or = LoadMetricsPlugin(config);
if (!metrics_plugin_or.ok()) {
errors.emplace_back(
absl::StrCat("Failed to load MetricsPlugin: ", metrics_plugin_or.status().message()));
continue;
}
plugin_from_name[config.name()] = std::move(metrics_plugin_or.value());
}
absl::StatusOr<StepControllerPtr> step_controller_or =
LoadStepControllerPlugin(spec.step_controller_config(), spec.nighthawk_traffic_template());
if (!step_controller_or.ok()) {
errors.emplace_back(absl::StrCat("Failed to load StepController plugin: ",
step_controller_or.status().message()));
}
std::vector<nighthawk::adaptive_load::MetricSpec> all_metric_specs;
for (const nighthawk::adaptive_load::MetricSpecWithThreshold& metric_threshold :
spec.metric_thresholds()) {
all_metric_specs.push_back(metric_threshold.metric_spec());
absl::StatusOr<ScoringFunctionPtr> scoring_function_or =
LoadScoringFunctionPlugin(metric_threshold.threshold_spec().scoring_function());
if (!scoring_function_or.ok()) {
errors.emplace_back(absl::StrCat("Failed to load ScoringFunction plugin: ",
scoring_function_or.status().message()));
}
}
for (const nighthawk::adaptive_load::MetricSpec& metric_spec :
spec.informational_metric_specs()) {
all_metric_specs.push_back(metric_spec);
}
for (const nighthawk::adaptive_load::MetricSpec& metric_spec : all_metric_specs) {
if (plugin_from_name.contains(metric_spec.metrics_plugin_name())) {
std::vector<std::string> supported_metrics =
plugin_from_name[metric_spec.metrics_plugin_name()]->GetAllSupportedMetricNames();
if (std::find(supported_metrics.begin(), supported_metrics.end(),
metric_spec.metric_name()) == supported_metrics.end()) {
errors.emplace_back(
absl::StrCat("Metric named '", metric_spec.metric_name(),
"' not implemented by plugin '", metric_spec.metrics_plugin_name(),
"'. Metrics implemented: ", absl::StrJoin(supported_metrics, ", "), "."));
}
} else {
errors.emplace_back(absl::StrCat(
"MetricSpec referred to nonexistent metrics_plugin_name '",
metric_spec.metrics_plugin_name(),
"'. You must declare the plugin in metrics_plugin_configs or use plugin ",
"'nighthawk.builtin'. Available plugins: ", absl::StrJoin(plugin_names, ", "), "."));
}
}
if (errors.size() > 0) {
return absl::InvalidArgumentError(absl::StrJoin(errors, "\n"));
}
return absl::OkStatus();
}

} // namespace Nighthawk
14 changes: 14 additions & 0 deletions source/adaptive_load/session_spec_proto_helper_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "nighthawk/adaptive_load/session_spec_proto_helper.h"

namespace Nighthawk {

class AdaptiveLoadSessionSpecProtoHelperImpl : public AdaptiveLoadSessionSpecProtoHelper {
public:
nighthawk::adaptive_load::AdaptiveLoadSessionSpec
SetSessionSpecDefaults(nighthawk::adaptive_load::AdaptiveLoadSessionSpec spec) override;

absl::Status
CheckSessionSpec(const nighthawk::adaptive_load::AdaptiveLoadSessionSpec& spec) override;
};

} // namespace Nighthawk
11 changes: 11 additions & 0 deletions test/adaptive_load/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ envoy_cc_test(
],
)

envoy_cc_test(
name = "session_spec_proto_helper_test",
srcs = ["session_spec_proto_helper_test.cc"],
repository = "@envoy",
deps = [
"//source/adaptive_load:session_spec_proto_helper_impl",
"//test/adaptive_load/fake_plugins/fake_metrics_plugin",
"//test/adaptive_load/fake_plugins/fake_step_controller",
],
)

envoy_cc_test(
name = "scoring_function_test",
srcs = ["scoring_function_test.cc"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,12 @@ FakeMetricsPluginConfigFactory::ValidateConfig(const Envoy::Protobuf::Message& m

REGISTER_FACTORY(FakeMetricsPluginConfigFactory, MetricsPluginConfigFactory);

envoy::config::core::v3::TypedExtensionConfig MakeFakeMetricsPluginTypedExtensionConfig(
const nighthawk::adaptive_load::FakeMetricsPluginConfig& config) {
envoy::config::core::v3::TypedExtensionConfig outer_config;
outer_config.set_name("nighthawk.fake_metrics_plugin");
outer_config.mutable_typed_config()->PackFrom(config);
return outer_config;
}

} // namespace Nighthawk
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,16 @@ class FakeMetricsPluginConfigFactory : public MetricsPluginConfigFactory {
// This factory is activated through LoadMetricsPlugin in plugin_util.h.
DECLARE_FACTORY(FakeMetricsPluginConfigFactory);

/**
* Creates a TypedExtensionConfig that activates a FakeMetricsPlugin by name with the given config
* proto.
*
* @param config The plugin-specific config proto to be packed into the typed_config Any.
*
* @return TypedExtensionConfig A proto that activates a FakeMetricsPlugin by name with a bundled
* config proto.
*/
envoy::config::core::v3::TypedExtensionConfig MakeFakeMetricsPluginTypedExtensionConfig(
const nighthawk::adaptive_load::FakeMetricsPluginConfig& config);

} // namespace Nighthawk
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "api/client/options.pb.h"

#include "test/adaptive_load/fake_plugins/fake_metrics_plugin/fake_metrics_plugin.h"
#include "test/adaptive_load/fake_plugins/fake_metrics_plugin/fake_metrics_plugin.pb.h"

#include "adaptive_load/plugin_loader.h"
#include "gmock/gmock.h"
Expand Down Expand Up @@ -114,5 +115,23 @@ TEST(FakeMetricsPlugin, GetAllSupportedMetricNamesReturnsCorrectValues) {
::testing::UnorderedElementsAre("metric1", "metric2"));
}

TEST(MakeFakeMetricsPluginTypedExtensionConfig, SetsCorrectPluginName) {
envoy::config::core::v3::TypedExtensionConfig activator =
MakeFakeMetricsPluginTypedExtensionConfig(
nighthawk::adaptive_load::FakeMetricsPluginConfig());
EXPECT_EQ(activator.name(), "nighthawk.fake_metrics_plugin");
}

TEST(MakeFakeMetricsPluginTypedExtensionConfig, PacksGivenConfigProto) {
nighthawk::adaptive_load::FakeMetricsPluginConfig expected_config;
expected_config.mutable_fake_metrics()->Add()->set_name("a");
envoy::config::core::v3::TypedExtensionConfig activator =
MakeFakeMetricsPluginTypedExtensionConfig(expected_config);
nighthawk::adaptive_load::FakeMetricsPluginConfig actual_config;
Envoy::MessageUtil::unpackTo(activator.typed_config(), actual_config);
EXPECT_EQ(expected_config.DebugString(), actual_config.DebugString());
EXPECT_TRUE(MessageDifferencer::Equivalent(expected_config, actual_config));
}

} // namespace
} // namespace Nighthawk
Loading