Skip to content

Commit ff11a9e

Browse files
committed
Ensuring we produce a valid JSON in case of empty string and -nan
1 parent bd755a5 commit ff11a9e

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

JSON_handler.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include <stdlib.h>
2424
#include <string.h>
25-
25+
#include <cmath> // For std::isnan
2626
#include "JSON_handler.h"
2727

2828

@@ -71,7 +71,39 @@ void json_handler::write_obj(const char * objectname, const char * format, ...)
7171
fprintf(m_json_file, "\"%s\": ", objectname);
7272
va_list argptr;
7373
va_start(argptr, format);
74-
vfprintf(m_json_file, format, argptr);
74+
// Check if format includes "%s", indicating a string is expected
75+
if (strstr(format, "%s") != nullptr) {
76+
// Use a temporary va_list to check the string argument without advancing the original
77+
va_list tmp_argptr;
78+
va_copy(tmp_argptr, argptr);
79+
const char *str_arg = va_arg(tmp_argptr, const char*);
80+
va_end(tmp_argptr);
81+
82+
if (str_arg == nullptr) {
83+
// Handle NULL strings by writing "null" to the JSON file
84+
fprintf(m_json_file, "null");
85+
} else {
86+
// Print the valid string argument
87+
vfprintf(m_json_file, format, argptr);
88+
}
89+
}
90+
// Check if the format expects a floating-point number
91+
else if (strstr(format, "f") != nullptr || strstr(format, "e") != nullptr || strstr(format, "g") != nullptr) {
92+
va_list tmp_argptr;
93+
va_copy(tmp_argptr, argptr);
94+
double value = va_arg(tmp_argptr, double);
95+
va_end(tmp_argptr);
96+
97+
if (std::isnan(value)) {
98+
fprintf(m_json_file, "null");
99+
} else {
100+
vfprintf(m_json_file, format, argptr);
101+
}
102+
}
103+
else {
104+
// For other format specifiers, proceed as usual
105+
vfprintf(m_json_file, format, argptr);
106+
}
75107
va_end(argptr);
76108
beutify();
77109
fprintf(m_json_file, ",");

run_stats.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -879,16 +879,19 @@ void run_stats::summarize(totals& result) const
879879
result.m_ask_sec = (double) (totals.m_set_cmd.m_ask + totals.m_get_cmd.m_ask) / test_duration_usec * 1000000;
880880
}
881881

882-
void result_print_to_json(json_handler * jsonhandler, const char * type, double ops,
882+
void result_print_to_json(json_handler * jsonhandler, const char * type, double ops_sec,
883883
double hits, double miss, double moved, double ask, double kbs, double kbs_rx, double kbs_tx,
884+
double latency, long ops,
884885
std::vector<float> quantile_list, struct hdr_histogram* latency_histogram,
885886
std::vector<unsigned int> timestamps,
886887
std::vector<one_sec_cmd_stats> timeserie_stats )
887888
{
888889
if (jsonhandler != NULL){ // Added for double verification in case someone accidently send NULL.
889890
jsonhandler->open_nesting(type);
890-
jsonhandler->write_obj("Count","%lld", hdr_total_count(latency_histogram));
891-
jsonhandler->write_obj("Ops/sec","%.2f", ops);
891+
const long hdr_count = hdr_total_count(latency_histogram);
892+
assert(hdr_count < ops && "reported ops and tracked ops via hdrhistogram are same");
893+
jsonhandler->write_obj("Count","%lld", hdr_count);
894+
jsonhandler->write_obj("Ops/sec","%.2f", ops_sec);
892895
jsonhandler->write_obj("Hits/sec","%.2f", hits);
893896
jsonhandler->write_obj("Misses/sec","%.2f", miss);
894897

@@ -899,9 +902,9 @@ void result_print_to_json(json_handler * jsonhandler, const char * type, double
899902
jsonhandler->write_obj("ASK/sec","%.2f", ask);
900903

901904
const bool has_samples = hdr_total_count(latency_histogram)>0;
902-
const double avg_latency = has_samples ? hdr_mean(latency_histogram)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
903-
const double min_latency = has_samples ? hdr_min(latency_histogram)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
904-
const double max_latency = has_samples ? hdr_max(latency_histogram)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
905+
const double avg_latency = latency;
906+
const double min_latency = has_samples ? (hdr_min(latency_histogram) * 1.0)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
907+
const double max_latency = has_samples ? (hdr_max(latency_histogram) * 1.0)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
905908
// to be retrocompatible
906909
jsonhandler->write_obj("Latency","%.3f", avg_latency);
907910
jsonhandler->write_obj("Average Latency","%.3f", avg_latency);
@@ -1240,6 +1243,8 @@ void run_stats::print_json(json_handler *jsonhandler, arbitrary_command_list& co
12401243
m_totals.m_ar_commands[i].m_bytes_sec,
12411244
m_totals.m_ar_commands[i].m_bytes_sec_rx,
12421245
m_totals.m_ar_commands[i].m_bytes_sec_tx,
1246+
m_totals.m_ar_commands[i].m_latency,
1247+
m_totals.m_ar_commands[i].m_ops,
12431248
quantiles_list,
12441249
arbitrary_command_latency_histogram,
12451250
timestamps,
@@ -1258,6 +1263,8 @@ void run_stats::print_json(json_handler *jsonhandler, arbitrary_command_list& co
12581263
m_totals.m_set_cmd.m_bytes_sec,
12591264
m_totals.m_set_cmd.m_bytes_sec_rx,
12601265
m_totals.m_set_cmd.m_bytes_sec_tx,
1266+
m_totals.m_set_cmd.m_latency,
1267+
m_totals.m_set_cmd.m_ops,
12611268
quantiles_list,
12621269
m_set_latency_histogram,
12631270
timestamps,
@@ -1271,6 +1278,8 @@ void run_stats::print_json(json_handler *jsonhandler, arbitrary_command_list& co
12711278
m_totals.m_get_cmd.m_bytes_sec,
12721279
m_totals.m_get_cmd.m_bytes_sec_rx,
12731280
m_totals.m_get_cmd.m_bytes_sec_tx,
1281+
m_totals.m_get_cmd.m_latency,
1282+
m_totals.m_get_cmd.m_ops,
12741283
quantiles_list,
12751284
m_get_latency_histogram,
12761285
timestamps,
@@ -1284,6 +1293,8 @@ void run_stats::print_json(json_handler *jsonhandler, arbitrary_command_list& co
12841293
0.0,
12851294
0.0,
12861295
0.0,
1296+
0.0,
1297+
m_totals.m_wait_cmd.m_ops,
12871298
quantiles_list,
12881299
m_wait_latency_histogram,
12891300
timestamps,
@@ -1299,6 +1310,8 @@ void run_stats::print_json(json_handler *jsonhandler, arbitrary_command_list& co
12991310
m_totals.m_bytes_sec,
13001311
m_totals.m_bytes_sec_rx,
13011312
m_totals.m_bytes_sec_tx,
1313+
m_totals.m_latency,
1314+
m_totals.m_ops,
13021315
quantiles_list,
13031316
m_totals.latency_histogram,
13041317
timestamps,

run_stats_types.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <stdio.h>
2424

2525
#include "run_stats_types.h"
26-
26+
#include <limits>
2727

2828

2929
one_sec_cmd_stats::one_sec_cmd_stats() :
@@ -36,8 +36,8 @@ one_sec_cmd_stats::one_sec_cmd_stats() :
3636
m_ask(0),
3737
m_total_latency(0),
3838
m_avg_latency(0.0),
39-
m_min_latency(0.0),
40-
m_max_latency(0.0) {
39+
m_min_latency(std::numeric_limits<double>::max()),
40+
m_max_latency(std::numeric_limits<double>::lowest()) {
4141
}
4242

4343

@@ -51,8 +51,8 @@ void one_sec_cmd_stats::reset() {
5151
m_ask = 0;
5252
m_total_latency = 0;
5353
m_avg_latency = 0;
54-
m_max_latency = 0;
55-
m_min_latency = 0;
54+
m_max_latency = std::numeric_limits<double>::lowest();
55+
m_min_latency = std::numeric_limits<double>::max();
5656
summarized_quantile_values.clear();
5757
}
5858

@@ -65,7 +65,9 @@ void one_sec_cmd_stats::merge(const one_sec_cmd_stats& other) {
6565
m_moved += other.m_moved;
6666
m_ask += other.m_ask;
6767
m_total_latency += other.m_total_latency;
68-
m_avg_latency = (double) m_total_latency / (double) m_ops / (double) LATENCY_HDR_RESULTS_MULTIPLIER;
68+
if (m_ops > 0) {
69+
m_avg_latency = (double) m_total_latency / (double) m_ops / (double) LATENCY_HDR_RESULTS_MULTIPLIER;
70+
}
6971
m_max_latency = other.m_max_latency > m_max_latency ? other.m_max_latency : m_max_latency;
7072
m_min_latency = other.m_min_latency < m_min_latency ? other.m_min_latency : m_min_latency;
7173
}
@@ -78,8 +80,8 @@ void one_sec_cmd_stats::summarize_quantiles(safe_hdr_histogram histogram, std::v
7880
summarized_quantile_values.push_back(value);
7981
}
8082
m_avg_latency = has_samples ? hdr_mean(histogram)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
81-
m_max_latency = has_samples ? hdr_max(histogram)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
82-
m_min_latency = has_samples ? hdr_min(histogram)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : 0.0;
83+
m_max_latency = has_samples ? (1.0 * hdr_max(histogram))/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : std::numeric_limits<double>::lowest();
84+
m_min_latency = has_samples ? (1.0 * hdr_min(histogram))/ (double) LATENCY_HDR_RESULTS_MULTIPLIER : std::numeric_limits<double>::max();;
8385
}
8486

8587
void one_sec_cmd_stats::update_op(unsigned int bytes_rx, unsigned int bytes_tx, unsigned int latency) {

0 commit comments

Comments
 (0)