h2load: Add qlog output support
This commit is contained in:
parent
1eb818b64c
commit
48e10c57da
|
@ -111,6 +111,7 @@ Config::Config()
|
||||||
encoder_header_table_size(4_k),
|
encoder_header_table_size(4_k),
|
||||||
data_fd(-1),
|
data_fd(-1),
|
||||||
log_fd(-1),
|
log_fd(-1),
|
||||||
|
qlog_file_base(),
|
||||||
port(0),
|
port(0),
|
||||||
default_port(0),
|
default_port(0),
|
||||||
connect_to_port(0),
|
connect_to_port(0),
|
||||||
|
@ -2200,6 +2201,13 @@ Options:
|
||||||
response time when using one worker thread, but may
|
response time when using one worker thread, but may
|
||||||
appear slightly out of order with multiple threads due
|
appear slightly out of order with multiple threads due
|
||||||
to buffering. Status code is -1 for failed streams.
|
to buffering. Status code is -1 for failed streams.
|
||||||
|
--qlog-file-base=<PATH>
|
||||||
|
Enable qlog output and specify base file name for qlogs.
|
||||||
|
Qlog is emitted for each connection.
|
||||||
|
For a given base name "base", each output file name
|
||||||
|
becomes "base.M.N.qlog" where M is worker ID and N is
|
||||||
|
client ID (e.g. "base.0.3.qlog").
|
||||||
|
Only effective in QUIC runs.
|
||||||
--connect-to=<HOST>[:<PORT>]
|
--connect-to=<HOST>[:<PORT>]
|
||||||
Host and port to connect instead of using the authority
|
Host and port to connect instead of using the authority
|
||||||
in <URI>.
|
in <URI>.
|
||||||
|
@ -2238,6 +2246,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
std::string datafile;
|
std::string datafile;
|
||||||
std::string logfile;
|
std::string logfile;
|
||||||
|
std::string qlog_base;
|
||||||
bool nreqs_set_manually = false;
|
bool nreqs_set_manually = false;
|
||||||
while (1) {
|
while (1) {
|
||||||
static int flag = 0;
|
static int flag = 0;
|
||||||
|
@ -2274,6 +2283,7 @@ int main(int argc, char **argv) {
|
||||||
{"groups", required_argument, &flag, 13},
|
{"groups", required_argument, &flag, 13},
|
||||||
{"tls13-ciphers", required_argument, &flag, 14},
|
{"tls13-ciphers", required_argument, &flag, 14},
|
||||||
{"no-udp-gso", no_argument, &flag, 15},
|
{"no-udp-gso", no_argument, &flag, 15},
|
||||||
|
{"qlog-file-base", required_argument, &flag, 16},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
auto c = getopt_long(argc, argv,
|
auto c = getopt_long(argc, argv,
|
||||||
|
@ -2536,6 +2546,10 @@ int main(int argc, char **argv) {
|
||||||
// --no-udp-gso
|
// --no-udp-gso
|
||||||
config.no_udp_gso = true;
|
config.no_udp_gso = true;
|
||||||
break;
|
break;
|
||||||
|
case 16:
|
||||||
|
// --qlog-file-base
|
||||||
|
qlog_base = optarg;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2720,6 +2734,14 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qlog_base.empty()) {
|
||||||
|
if (!config.is_quic()) {
|
||||||
|
std::cerr << "Warning: --qlog-file-base: only effective in quic, ignoring." << std::endl;
|
||||||
|
} else {
|
||||||
|
config.qlog_file_base = qlog_base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct sigaction act {};
|
struct sigaction act {};
|
||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &act, nullptr);
|
sigaction(SIGPIPE, &act, nullptr);
|
||||||
|
|
|
@ -109,6 +109,8 @@ struct Config {
|
||||||
int data_fd;
|
int data_fd;
|
||||||
// file descriptor to write per-request stats to.
|
// file descriptor to write per-request stats to.
|
||||||
int log_fd;
|
int log_fd;
|
||||||
|
// base file name of qlog output files
|
||||||
|
std::string qlog_file_base;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint16_t default_port;
|
uint16_t default_port;
|
||||||
uint16_t connect_to_port;
|
uint16_t connect_to_port;
|
||||||
|
@ -340,6 +342,7 @@ struct Client {
|
||||||
std::array<Crypto, 2> crypto;
|
std::array<Crypto, 2> crypto;
|
||||||
size_t max_pktlen;
|
size_t max_pktlen;
|
||||||
bool close_requested;
|
bool close_requested;
|
||||||
|
FILE *qlog_file;
|
||||||
} quic;
|
} quic;
|
||||||
ev_timer request_timeout_watcher;
|
ev_timer request_timeout_watcher;
|
||||||
addrinfo *next_addr;
|
addrinfo *next_addr;
|
||||||
|
@ -481,6 +484,7 @@ struct Client {
|
||||||
const uint8_t *data, size_t datalen);
|
const uint8_t *data, size_t datalen);
|
||||||
int quic_pkt_timeout();
|
int quic_pkt_timeout();
|
||||||
void quic_restart_pkt_timer();
|
void quic_restart_pkt_timer();
|
||||||
|
void quic_write_qlog(const void *data, size_t datalen);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace h2load
|
} // namespace h2load
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
#include "h2load_http3_session.h"
|
#include "h2load_http3_session.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace h2load {
|
namespace h2load {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -284,6 +286,20 @@ auto quic_method = SSL_QUIC_METHOD{
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
// qlog write callback -- excerpted from ngtcp2/examples/client_base.cc
|
||||||
|
namespace {
|
||||||
|
void qlog_write_cb(void *user_data, uint32_t flags, const void *data,
|
||||||
|
size_t datalen) {
|
||||||
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
c->quic_write_qlog(data, datalen);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Client::quic_write_qlog(const void *data, size_t datalen) {
|
||||||
|
assert(quic.qlog_file != nullptr);
|
||||||
|
fwrite(data, 1, datalen, quic.qlog_file);
|
||||||
|
}
|
||||||
|
|
||||||
int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
||||||
const sockaddr *remote_addr, socklen_t remote_addrlen) {
|
const sockaddr *remote_addr, socklen_t remote_addrlen) {
|
||||||
int rv;
|
int rv;
|
||||||
|
@ -354,6 +370,17 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
||||||
settings.log_printf = debug_log_printf;
|
settings.log_printf = debug_log_printf;
|
||||||
}
|
}
|
||||||
settings.initial_ts = timestamp(worker->loop);
|
settings.initial_ts = timestamp(worker->loop);
|
||||||
|
if (!config->qlog_file_base.empty()) {
|
||||||
|
assert(quic.qlog_file == nullptr);
|
||||||
|
std::ostringstream oss(config->qlog_file_base, std::ios::app);
|
||||||
|
oss << '.' << worker->id << '.' << id << ".qlog";
|
||||||
|
quic.qlog_file = fopen(oss.str().c_str(), "w");
|
||||||
|
if (quic.qlog_file == nullptr) {
|
||||||
|
std::cerr << "Failed to open a qlog file: " << oss.str() << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
settings.qlog.write = qlog_write_cb;
|
||||||
|
}
|
||||||
|
|
||||||
ngtcp2_transport_params params;
|
ngtcp2_transport_params params;
|
||||||
ngtcp2_transport_params_default(¶ms);
|
ngtcp2_transport_params_default(¶ms);
|
||||||
|
@ -393,7 +420,13 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::quic_free() { ngtcp2_conn_del(quic.conn); }
|
void Client::quic_free() {
|
||||||
|
ngtcp2_conn_del(quic.conn);
|
||||||
|
if (quic.qlog_file != nullptr) {
|
||||||
|
fclose(quic.qlog_file);
|
||||||
|
quic.qlog_file = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::quic_close_connection() {
|
void Client::quic_close_connection() {
|
||||||
if (!quic.conn) {
|
if (!quic.conn) {
|
||||||
|
|
Loading…
Reference in New Issue