From 7de3642de05e32ba4a51299168003affe14440c3 Mon Sep 17 00:00:00 2001 From: Anthony Monthe Date: Thu, 24 Jan 2019 01:34:25 +0000 Subject: [PATCH 1/4] Added JSON output --- src/wrk.c | 103 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 23 deletions(-) diff --git a/src/wrk.c b/src/wrk.c index 51f46f72..6fea89d0 100644 --- a/src/wrk.c +++ b/src/wrk.c @@ -13,6 +13,7 @@ static struct config { bool delay; bool dynamic; bool latency; + bool json_format; char *host; char *script; SSL_CTX *ctx; @@ -42,7 +43,7 @@ static void handler(int sig) { } static void usage() { - printf("Usage: wrk \n" + printf("Usage: wrk \n"// " Options: \n" " -c, --connections Connections to keep open \n" " -d, --duration Duration of test \n" @@ -51,6 +52,7 @@ static void usage() { " -s, --script Load Lua script file \n" " -H, --header Add header to request \n" " --latency Print latency statistics \n" + " --json-format Print output as JSON \n" " --timeout Socket/request timeout \n" " -v, --version Print version details \n" " \n" @@ -135,8 +137,10 @@ int main(int argc, char **argv) { sigaction(SIGINT, &sa, NULL); char *time = format_time_s(cfg.duration); - printf("Running %s test @ %s\n", time, url); - printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections); + if (cfg.json_format == false) { + printf("Running %s test @ %s\n", time, url); + printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections); + } uint64_t start = time_us(); uint64_t complete = 0; @@ -170,30 +174,78 @@ int main(int argc, char **argv) { stats_correct(statistics.latency, interval); } - print_stats_header(); - print_stats("Latency", statistics.latency, format_time_us); - print_stats("Req/Sec", statistics.requests, format_metric); - if (cfg.latency) print_stats_latency(statistics.latency); + if (cfg.json_format == false) { + print_stats_header(); + print_stats("Latency", statistics.latency, format_time_us); + print_stats("Req/Sec", statistics.requests, format_metric); + if (cfg.latency) print_stats_latency(statistics.latency); - char *runtime_msg = format_time_us(runtime_us); + char *runtime_msg = format_time_us(runtime_us); - printf(" %"PRIu64" requests in %s, %sB read\n", complete, runtime_msg, format_binary(bytes)); - if (errors.connect || errors.read || errors.write || errors.timeout) { - printf(" Socket errors: connect %d, read %d, write %d, timeout %d\n", - errors.connect, errors.read, errors.write, errors.timeout); - } + printf(" %"PRIu64" requests in %s, %sB read\n", complete, runtime_msg, format_binary(bytes)); + if (errors.connect || errors.read || errors.write || errors.timeout) { + printf(" Socket errors: connect %d, read %d, write %d, timeout %d\n", + errors.connect, errors.read, errors.write, errors.timeout); + } - if (errors.status) { - printf(" Non-2xx or 3xx responses: %d\n", errors.status); - } + if (errors.status) { + printf(" Non-2xx or 3xx responses: %d\n", errors.status); + } - printf("Requests/sec: %9.2Lf\n", req_per_s); - printf("Transfer/sec: %10sB\n", format_binary(bytes_per_s)); + printf("Requests/sec: %9.2Lf\n", req_per_s); + printf("Transfer/sec: %10sB\n", format_binary(bytes_per_s)); - if (script_has_done(L)) { - script_summary(L, runtime_us, complete, bytes); - script_errors(L, &errors); - script_done(L, statistics.latency, statistics.requests); + if (script_has_done(L)) { + script_summary(L, runtime_us, complete, bytes); + script_errors(L, &errors); + script_done(L, statistics.latency, statistics.requests); + } + } else { + long double req_mean = stats_mean(statistics.requests); + long double req_stdev = stats_stdev(statistics.requests, req_mean); + long double req_within = stats_within_stdev(statistics.requests, req_mean, req_stdev, 1); + long double lat_mean = stats_mean(statistics.latency); + long double lat_stdev = stats_stdev(statistics.latency, lat_mean); + long double lat_within = stats_within_stdev(statistics.latency, lat_mean, lat_stdev, 1); + long double lat_perc_50 = stats_percentile(statistics.latency, 50.0) / 1000000.0; + long double lat_perc_75 = stats_percentile(statistics.latency, 75.0) / 1000000.0; + long double lat_perc_90 = stats_percentile(statistics.latency, 90.0) / 1000000.0; + long double lat_perc_95 = stats_percentile(statistics.latency, 95.0) / 1000000.0; + long double lat_perc_99 = stats_percentile(statistics.latency, 99.0) / 1000000.0; + printf("{\n"); + printf(" \"threads\": %"PRIu64",\n", cfg.threads); + printf(" \"connections\": %"PRIu64",\n", cfg.connections); + printf(" \"duration\": %"PRIu64",\n", cfg.duration); + if (cfg.script) { + printf(" \"script\": %s,\n", cfg.script); + } else { + printf(" \"script\": null,\n"); + } + printf(" \"runtime\": %"PRIu64",\n", runtime_us); + printf(" \"bytes_per_sec\": %Lf,\n", bytes_per_s); + printf(" \"requests_per_sec\": %Lf,\n", req_per_s); + printf(" \"requests_mean\": %Lf,\n", req_mean); + printf(" \"requests_stdev\": %Lf,\n", req_stdev); + printf(" \"requests_min\": %"PRIu64",\n", statistics.requests->min); + printf(" \"requests_max\": %"PRIu64",\n", statistics.requests->max); + printf(" \"requests_within_stdev\": %.2Lf,\n", req_within); + printf(" \"latency_mean\": %Lf,\n", lat_mean/1000000.0); + printf(" \"latency_stdev\": %Lf,\n", lat_stdev/1000000.0); + printf(" \"latency_min\": %f,\n", statistics.latency->min/1000000.0); + printf(" \"latency_max\": %f,\n", statistics.latency->max/1000000.0); + printf(" \"latency_within_stdev\": %.2Lf,\n", lat_within); + printf(" \"latency_percentile_50\": %.2Lf,\n", lat_perc_50); + printf(" \"latency_percentile_75\": %.2Lf,\n", lat_perc_75); + printf(" \"latency_percentile_90\": %.2Lf,\n", lat_perc_90); + printf(" \"latency_percentile_90\": %.2Lf,\n", lat_perc_90); + printf(" \"latency_percentile_95\": %.2Lf,\n", lat_perc_95); + printf(" \"latency_percentile_99\": %.2Lf,\n", lat_perc_99); + printf(" \"errors_connect\": %d,\n", errors.connect); + printf(" \"errors_read\": %d,\n", errors.read); + printf(" \"errors_write\": %d,\n", errors.write); + printf(" \"errors_timeout\": %d,\n", errors.timeout); + printf(" \"errors_status\": %d\n", errors.status); + printf("}"); } return 0; @@ -474,6 +526,7 @@ static struct option longopts[] = { { "header", required_argument, NULL, 'H' }, { "latency", no_argument, NULL, 'L' }, { "timeout", required_argument, NULL, 'T' }, + { "json-format", no_argument, NULL, 'j' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } @@ -488,8 +541,9 @@ static int parse_args(struct config *cfg, char **url, struct http_parser_url *pa cfg->connections = 10; cfg->duration = 10; cfg->timeout = SOCKET_TIMEOUT_MS; + cfg->json_format = false; - while ((c = getopt_long(argc, argv, "t:c:d:s:H:T:Lrv?", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "t:c:d:s:H:T:Lrv?j", longopts, NULL)) != -1) { switch (c) { case 't': if (scan_metric(optarg, &cfg->threads)) return -1; @@ -509,6 +563,9 @@ static int parse_args(struct config *cfg, char **url, struct http_parser_url *pa case 'L': cfg->latency = true; break; + case 'j': + cfg->json_format = true; + break; case 'T': if (scan_time(optarg, &cfg->timeout)) return -1; cfg->timeout *= 1000; From 1039c065ab695498c363633b65bac0da7b591475 Mon Sep 17 00:00:00 2001 From: Anthony Monthe Date: Thu, 24 Jan 2019 01:35:09 +0000 Subject: [PATCH 2/4] Added VIM file to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e25de364..b0a9b64a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ obj/ wrk +*.sw[pon] From 134d2ded9f9e11d612023141d18e474c5174d068 Mon Sep 17 00:00:00 2001 From: Anthony Monthe Date: Thu, 24 Jan 2019 01:39:25 +0000 Subject: [PATCH 3/4] Update README about JSON --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ac61e0d9..7333020b 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ --latency: print detailed latency statistics + -j --json-format: print output as JSON format + --timeout: record a timeout if a response is not received within this amount of time. From 797961d952e818cde350d5db3815ccbfb83ff05e Mon Sep 17 00:00:00 2001 From: Anthony Monthe Date: Thu, 24 Jan 2019 02:40:57 +0000 Subject: [PATCH 4/4] Added more infos and little fixes --- src/wrk.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/wrk.c b/src/wrk.c index 6fea89d0..519b9f29 100644 --- a/src/wrk.c +++ b/src/wrk.c @@ -43,7 +43,7 @@ static void handler(int sig) { } static void usage() { - printf("Usage: wrk \n"// + printf("Usage: wrk \n" " Options: \n" " -c, --connections Connections to keep open \n" " -d, --duration Duration of test \n" @@ -52,7 +52,7 @@ static void usage() { " -s, --script Load Lua script file \n" " -H, --header Add header to request \n" " --latency Print latency statistics \n" - " --json-format Print output as JSON \n" + " -j --json-format Print output as JSON \n" " --timeout Socket/request timeout \n" " -v, --version Print version details \n" " \n" @@ -137,7 +137,7 @@ int main(int argc, char **argv) { sigaction(SIGINT, &sa, NULL); char *time = format_time_s(cfg.duration); - if (cfg.json_format == false) { + if (!cfg.json_format) { printf("Running %s test @ %s\n", time, url); printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections); } @@ -174,7 +174,7 @@ int main(int argc, char **argv) { stats_correct(statistics.latency, interval); } - if (cfg.json_format == false) { + if (!cfg.json_format) { print_stats_header(); print_stats("Latency", statistics.latency, format_time_us); print_stats("Req/Sec", statistics.requests, format_metric); @@ -213,16 +213,20 @@ int main(int argc, char **argv) { long double lat_perc_95 = stats_percentile(statistics.latency, 95.0) / 1000000.0; long double lat_perc_99 = stats_percentile(statistics.latency, 99.0) / 1000000.0; printf("{\n"); + printf(" \"url\": \"%s\",\n", url); printf(" \"threads\": %"PRIu64",\n", cfg.threads); printf(" \"connections\": %"PRIu64",\n", cfg.connections); printf(" \"duration\": %"PRIu64",\n", cfg.duration); + printf(" \"timeout\": %"PRIu64",\n", cfg.timeout); if (cfg.script) { - printf(" \"script\": %s,\n", cfg.script); + printf(" \"script\": \"%s\",\n", cfg.script); } else { printf(" \"script\": null,\n"); } - printf(" \"runtime\": %"PRIu64",\n", runtime_us); + printf(" \"runtime_us\": %"PRIu64",\n", runtime_us); + printf(" \"bytes\": %"PRIu64",\n", bytes); printf(" \"bytes_per_sec\": %Lf,\n", bytes_per_s); + printf(" \"requests_count\": %"PRIu64",\n", statistics.requests->count); printf(" \"requests_per_sec\": %Lf,\n", req_per_s); printf(" \"requests_mean\": %Lf,\n", req_mean); printf(" \"requests_stdev\": %Lf,\n", req_stdev); @@ -237,7 +241,6 @@ int main(int argc, char **argv) { printf(" \"latency_percentile_50\": %.2Lf,\n", lat_perc_50); printf(" \"latency_percentile_75\": %.2Lf,\n", lat_perc_75); printf(" \"latency_percentile_90\": %.2Lf,\n", lat_perc_90); - printf(" \"latency_percentile_90\": %.2Lf,\n", lat_perc_90); printf(" \"latency_percentile_95\": %.2Lf,\n", lat_perc_95); printf(" \"latency_percentile_99\": %.2Lf,\n", lat_perc_99); printf(" \"errors_connect\": %d,\n", errors.connect);