Skip to content

Commit

Permalink
Merge 8e1b3d1 into 4546c22
Browse files Browse the repository at this point in the history
  • Loading branch information
xnuter authored Jun 12, 2021
2 parents 4546c22 + 8e1b3d1 commit 8417273
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
args: --release
args: --release --features full

- name: Create artifact directory
run: mkdir artifacts
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build
run: cargo build --verbose
run: cargo build --verbose --features full
- name: Run tests
run: cargo test --verbose

- name: Run tests full
run: cargo test --verbose --features full
- name: Run tests tls
run: cargo test --verbose --features tls-native

26 changes: 17 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "perf-gauge"
version = "0.1.8"
version = "0.1.9"
authors = ["Eugene Retunsky"]
license = "MIT OR Apache-2.0"
edition = "2018"
Expand All @@ -16,8 +16,7 @@ Gauging performance of network services. Snapshot or continuous, supports Promet

[dependencies]
clap = "3.0.0-beta.1"
reqwest = { version = "0.11", features = ["hyper-tls", "stream"] }
base64="0.13"
base64 = "0.13"
derive_builder = "0.9"
log = "0.4"
log4rs = "1"
Expand All @@ -32,16 +31,25 @@ async-trait = "0.1"
bytesize = "1.0"
humantime = "2.0"
regex = "1.3"
prometheus = {version = "0.11", features=["push"] }
rand = "0.8"
futures-util = "0.3"
hyper = { version = "0.14", features = ["full"] }
prometheus = { version = "0.11", features = ["push"], default-features = false, optional = true }
hyper-tls = {version = "0.5", default-features = false, optional = true }
native-tls = {version = "0.2", default-features = false, optional = true }
tokio-native-tls = {version = "0.3", default-features = false, optional = true }
hyper-boring = {version = "2", default-features = false, optional = true }
boring = {version = "1", default-features = false, optional = true }

[dev-dependencies]
mockito = "0.28"
tokio-test = "0.4"

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3
[features]
default = []
report_to_prometheus = ["prometheus"]
tls = ["hyper-tls"]
tls-native = ["tls", "native-tls", "tokio-native-tls"]
tls-boring = ["tls", "hyper-boring", "boring"]
full = ["report_to_prometheus", "tls-native"]
full-boring = ["report_to_prometheus", "tls-boring"]
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,29 +122,27 @@ FLAGS:
--conn_reuse If connections should be re-used
--http2_only Enforce HTTP/2 only
--ignore_cert Allow self signed certificates. Applies to the target (not proxy).
--store_cookies If cookies should be stored
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-B, --body <BODY> Body of the request in base64. Optional.
-H, --header <HEADER>... Headers in "Name:Value" form. Can be provided multiple times.
-M, --method <METHOD> Method. By default GET
--tunnel <TUNNEL> HTTP Tunnel used for connection, e.g. http://my-proxy.org
```

For example, test an endpoint using a single run, 5 seconds (max possible request rate):

```bash
$ perf-gauge --concurrency 10 \
--duration 10s \
--duration 1m \
http http://localhost/10kb --conn_reuse
```

Parameters:

* `--concurrency 10` - the number of clients generating load concurrently
* `--duration 60s` - step duration `60s`
* `--duration 1m` - step duration `1m` (or `10s`, `5m`, etc.)
* `http http://local-nginx.org/10kb --conn_reuse` - run in `http` mode to the given endpoint, reusing connections.

Reporting performance metrics to Prometheus
Expand All @@ -160,15 +158,15 @@ export PROMETHEUS_HOST=10.138.0.2
$ perf-gauge --concurrency 10 \
--rate 1000 --rate_step 1000 --rate_max 25000 \
--max_iter 15 \
--duration 60s \
--duration 1m \
--name nginx-direct \
--prometheus $PROMETHEUS_HOST:9091 \
http https://localhost/10kb --conn_reuse --ignore_cert
```

* `--concurrency 10` - the number of clients generating load concurrently
* `--rate 1000 --rate_step 1000 --rate_max 25000` - start with rate 1000 rps, then add 1000 rps after each step until it reaches 25k.
* `--duration 60s` - step duration `60s`
* `--duration 1m` - step duration `1m`
* `--max_iter 15` - perform `15` iterations at the max rate
* `--name nginx-direct` - the name of the test (used for reporting metrics to `prometheus`)
* `--prometheus $PROMETHEUS_HOST:9091` - push-gateway `host:port` to send metrics to Prometheus.
Expand Down
63 changes: 46 additions & 17 deletions src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ use crate::bench_session::{BenchSession, BenchSessionBuilder, RateLadder, RateLa
/// except according to those terms.
use crate::http_bench_session::{HttpBenchAdapter, HttpBenchAdapterBuilder};
use crate::metrics::{DefaultConsoleReporter, ExternalMetricsServiceReporter};
use crate::prometheus_reporter::PrometheusReporter;
use clap::{clap_app, ArgMatches};
use core::fmt;
use std::net::SocketAddr;
use std::process::exit;
use std::str::FromStr;
use std::sync::Arc;
Expand Down Expand Up @@ -61,10 +59,8 @@ impl BenchmarkConfig {
(@subcommand http =>
(about: "Run in HTTP(S) mode")
(version: "0.1.8")
(@arg TUNNEL: --tunnel +takes_value "HTTP Tunnel used for connection, e.g. http://my-proxy.org")
(@arg IGNORE_CERT: --ignore_cert "Allow self signed certificates. Applies to the target (not proxy).")
(@arg IGNORE_CERT: --ignore_cert "Allow self signed certificates.")
(@arg CONN_REUSE: --conn_reuse "If connections should be re-used")
(@arg STORE_COOKIES: --store_cookies "If cookies should be stored")
(@arg HTTP2_ONLY: --http2_only "Enforce HTTP/2 only")
(@arg TARGET: +required ... "Target, e.g. https://my-service.com:8443/8kb Can be multiple ones (with random choice balancing)")
(@arg METHOD: --method -M +takes_value "Method. By default GET")
Expand Down Expand Up @@ -122,6 +118,44 @@ impl BenchmarkConfig {
.expect("RateLadderBuilder failed")
};

Ok(BenchmarkConfigBuilder::default()
.name(test_case_name.clone())
.rate_ladder(rate_ladder)
.concurrency(parse_num(concurrency, "Cannot parse CONCURRENCY"))
.verbose(false)
.continuous(matches.is_present("CONTINUOUS"))
.mode(BenchmarkConfig::build_mode(&matches))
.reporters(BenchmarkConfig::build_metric_destinations(
test_case_name,
matches,
))
.build()
.expect("BenchmarkConfig failed"))
}

#[cfg(not(feature = "report_to_prometheus"))]
fn build_metric_destinations(
test_case_name: Option<String>,
matches: ArgMatches,
) -> Vec<Arc<Box<dyn ExternalMetricsServiceReporter + Send + Sync>>> {
if matches.value_of("PROMETHEUS_ADDR").is_some() {
println!("Prometheus is not supported in this configuration");
exit(-1);
}

vec![Arc::new(Box::new(DefaultConsoleReporter::new(
test_case_name,
)))]
}

#[cfg(feature = "report_to_prometheus")]
fn build_metric_destinations(
test_case_name: Option<String>,
matches: ArgMatches,
) -> Vec<Arc<Box<dyn ExternalMetricsServiceReporter + Send + Sync>>> {
use crate::prometheus_reporter::PrometheusReporter;
use std::net::SocketAddr;

let mut metrics_destinations: Vec<
Arc<Box<dyn ExternalMetricsServiceReporter + Send + Sync + 'static>>,
> = vec![Arc::new(Box::new(DefaultConsoleReporter::new(
Expand All @@ -139,20 +173,17 @@ impl BenchmarkConfig {
))));
}

Ok(BenchmarkConfigBuilder::default()
.name(test_case_name)
.rate_ladder(rate_ladder)
.concurrency(parse_num(concurrency, "Cannot parse CONCURRENCY"))
.verbose(false)
.continuous(matches.is_present("CONTINUOUS"))
.mode(BenchmarkConfig::build_mode(&matches))
.reporters(metrics_destinations)
.build()
.expect("BenchmarkConfig failed"))
metrics_destinations
}

fn build_mode(matches: &ArgMatches) -> BenchmarkMode {
let mode = if let Some(config) = matches.subcommand_matches("http") {
#[cfg(feature = "tls-boring")]
if config.is_present("IGNORE_CERT") {
println!("--ignore_cert is not supported for BoringSSL");
exit(-1);
}

let http_config = HttpBenchAdapterBuilder::default()
.url(
config
Expand All @@ -161,10 +192,8 @@ impl BenchmarkConfig {
.map(|s| s.to_string())
.collect(),
)
.tunnel(config.value_of("TUNNEL").map(|s| s.to_string()))
.ignore_cert(config.is_present("IGNORE_CERT"))
.conn_reuse(config.is_present("CONN_REUSE"))
.store_cookies(config.is_present("STORE_COOKIES"))
.http2_only(config.is_present("HTTP2_ONLY"))
.method(config.value_of("METHOD").unwrap_or("GET").to_string())
.headers(BenchmarkConfig::get_multiple_values(config, "HEADER"))
Expand Down
Loading

0 comments on commit 8417273

Please sign in to comment.