Skip to content

Commit 94e5866

Browse files
authored
tokio-quiche: do not generate an error log for Handshake errors and quiche errors
These errors are expected since they can be generated by the peer
1 parent 5f76e01 commit 94e5866

2 files changed

Lines changed: 31 additions & 3 deletions

File tree

‎tokio-quiche/src/http3/driver/mod.rs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ use self::streams::WaitForUpstreamCapacity;
7777
use crate::http3::settings::Http3Settings;
7878
use crate::http3::H3AuditStats;
7979
use crate::metrics::Metrics;
80+
use crate::quic::HandshakeError;
8081
use crate::quic::HandshakeInfo;
8182
use crate::quic::QuicCommand;
8283
use crate::quic::QuicheConnection;
@@ -1454,7 +1455,19 @@ impl<H: DriverHooks> ApplicationOverQuic for H3Driver<H> {
14541455

14551456
let Some(h3_err) = work_loop_error.downcast_ref::<H3ConnectionError>()
14561457
else {
1457-
log::error!("Found non-H3ConnectionError"; "error" => %work_loop_error);
1458+
// Errors returned by the IoWorker rather than the driver are
1459+
// expected and already counted in metrics:
1460+
// - `HandshakeError`: with 0-RTT early data, the handshake can
1461+
// still fail (e.g. time out) after the application was started.
1462+
// - `quiche::Error`: the connection was closed by quiche, typically
1463+
// because of a peer protocol violation.
1464+
if work_loop_error.is::<HandshakeError>() ||
1465+
work_loop_error.is::<quiche::Error>()
1466+
{
1467+
log::debug!("connection closed by IoWorker"; "error" => %work_loop_error);
1468+
} else {
1469+
log::error!("Found non-H3ConnectionError"; "error" => %work_loop_error);
1470+
}
14581471
return;
14591472
};
14601473

‎tokio-quiche/tests/integration_tests/zero_rtt.rs‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ use crate::integration_tests::Http3Settings;
3131
use crate::integration_tests::QuicSettings;
3232
use crate::integration_tests::TestConnectionHook;
3333
use datagram_socket::QuicAuditStats;
34+
use foundations::telemetry::with_test_telemetry;
35+
use foundations::telemetry::TestTelemetryContext;
3436
use futures::SinkExt;
3537
use h3i;
3638
use h3i::actions::h3::send_headers_frame;
@@ -410,8 +412,8 @@ impl EarlyDataClient {
410412
/// A client that resumes a session with 0-RTT, but never completes the
411413
/// handshake while it keeps sending 0-RTT packets, must still be subject to
412414
/// the handshake timeout, even though the application was already started.
413-
#[tokio::test]
414-
async fn handshake_timeout_after_0_rtt() {
415+
#[with_test_telemetry(tokio::test)]
416+
async fn handshake_timeout_after_0_rtt(cx: TestTelemetryContext) {
415417
const HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(1);
416418

417419
let mut server = EarlyDataServer::start(HANDSHAKE_TIMEOUT).await;
@@ -442,4 +444,17 @@ async fn handshake_timeout_after_0_rtt() {
442444

443445
server.assert_handshake_timeout(&audit_stats);
444446
assert!(failed_handshake_timeouts() > failed_handshake_timeouts_before);
447+
448+
// A handshake timeout is an expected outcome, it must not be logged as an
449+
// error by the application.
450+
let error_logs: Vec<_> = cx
451+
.log_records()
452+
.iter()
453+
.filter(|record| record.level.as_str() == "ERROR")
454+
.map(|record| record.message.clone())
455+
.collect();
456+
assert!(
457+
error_logs.is_empty(),
458+
"unexpected error logs: {error_logs:?}"
459+
);
445460
}

0 commit comments

Comments
 (0)