diff --git a/dc/s2n-quic-dc/Cargo.toml b/dc/s2n-quic-dc/Cargo.toml index ccb46f971..818c612a2 100644 --- a/dc/s2n-quic-dc/Cargo.toml +++ b/dc/s2n-quic-dc/Cargo.toml @@ -12,7 +12,7 @@ exclude = ["corpus.tar.gz"] [features] default = ["tokio"] -testing = ["bolero-generator", "s2n-quic-core/testing"] +testing = ["bolero-generator", "s2n-quic-core/testing", "tracing-subscriber"] tokio = ["tokio/io-util", "tokio/net", "tokio/rt-multi-thread", "tokio/time"] [dependencies] @@ -40,6 +40,7 @@ slotmap = "1" thiserror = "1" tokio = { version = "1", default-features = false, features = ["sync"] } tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true } zerocopy = { version = "0.7", features = ["derive"] } zeroize = "1" parking_lot = "0.12" @@ -51,6 +52,7 @@ insta = "1" s2n-codec = { path = "../../common/s2n-codec", features = ["testing"] } s2n-quic-core = { path = "../../quic/s2n-quic-core", features = ["testing"] } tokio = { version = "1", features = ["full"] } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } [lints.rust.unexpected_cfgs] level = "warn" diff --git a/dc/s2n-quic-dc/src/event.rs b/dc/s2n-quic-dc/src/event.rs index 8445158d5..2e883aaf7 100644 --- a/dc/s2n-quic-dc/src/event.rs +++ b/dc/s2n-quic-dc/src/event.rs @@ -28,3 +28,18 @@ impl Meta for api::EndpointMeta { mod generated; pub use generated::*; + +pub mod metrics { + pub use crate::event::generated::metrics::*; + pub use s2n_quic_core::event::metrics::Recorder; + + pub mod aggregate { + pub use crate::event::generated::metrics::aggregate::*; + pub use s2n_quic_core::event::metrics::aggregate::{info, Info, Recorder, Registry}; + + pub mod probe { + pub use crate::event::generated::metrics::probe::*; + pub use s2n_quic_core::event::metrics::aggregate::probe::dynamic; + } + } +} diff --git a/dc/s2n-quic-dc/src/event/generated.rs b/dc/s2n-quic-dc/src/event/generated.rs index e821d89d0..5dac84e1c 100644 --- a/dc/s2n-quic-dc/src/event/generated.rs +++ b/dc/s2n-quic-dc/src/event/generated.rs @@ -6,6 +6,7 @@ // changes should be made there. use super::*; +pub(crate) mod metrics; pub mod api { #![doc = r" This module contains events that are emitted to the [`Subscriber`](crate::event::Subscriber)"] use super::*; @@ -2673,82 +2674,6 @@ mod traits { } } } -pub mod metrics { - use super::*; - use core::sync::atomic::{AtomicU32, Ordering}; - use s2n_quic_core::event::metrics::Recorder; - #[derive(Debug)] - pub struct Subscriber - where - S::ConnectionContext: Recorder, - { - subscriber: S, - } - impl Subscriber - where - S::ConnectionContext: Recorder, - { - pub fn new(subscriber: S) -> Self { - Self { subscriber } - } - } - pub struct Context { - recorder: R, - application_write: AtomicU32, - application_read: AtomicU32, - } - impl super::Subscriber for Subscriber - where - S::ConnectionContext: Recorder, - { - type ConnectionContext = Context; - fn create_connection_context( - &self, - meta: &api::ConnectionMeta, - info: &api::ConnectionInfo, - ) -> Self::ConnectionContext { - Context { - recorder: self.subscriber.create_connection_context(meta, info), - application_write: AtomicU32::new(0), - application_read: AtomicU32::new(0), - } - } - #[inline] - fn on_application_write( - &self, - context: &Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ApplicationWrite, - ) { - context.application_write.fetch_add(1, Ordering::Relaxed); - self.subscriber - .on_application_write(&context.recorder, meta, event); - } - #[inline] - fn on_application_read( - &self, - context: &Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ApplicationRead, - ) { - context.application_read.fetch_add(1, Ordering::Relaxed); - self.subscriber - .on_application_read(&context.recorder, meta, event); - } - } - impl Drop for Context { - fn drop(&mut self) { - self.recorder.increment_counter( - "application_write", - self.application_write.load(Ordering::Relaxed) as _, - ); - self.recorder.increment_counter( - "application_read", - self.application_read.load(Ordering::Relaxed) as _, - ); - } - } -} #[cfg(any(test, feature = "testing"))] pub mod testing { use super::*; diff --git a/dc/s2n-quic-dc/src/event/generated/metrics.rs b/dc/s2n-quic-dc/src/event/generated/metrics.rs new file mode 100644 index 000000000..5a38b228f --- /dev/null +++ b/dc/s2n-quic-dc/src/event/generated/metrics.rs @@ -0,0 +1,82 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// DO NOT MODIFY THIS FILE +// This file was generated with the `s2n-quic-events` crate and any required +// changes should be made there. + +use crate::event::{self, api, metrics::Recorder}; +use core::sync::atomic::{AtomicU32, Ordering}; +pub(crate) mod aggregate; +pub(crate) mod probe; +#[derive(Debug)] +pub struct Subscriber +where + S::ConnectionContext: Recorder, +{ + subscriber: S, +} +impl Subscriber +where + S::ConnectionContext: Recorder, +{ + pub fn new(subscriber: S) -> Self { + Self { subscriber } + } +} +pub struct Context { + recorder: R, + application_write: AtomicU32, + application_read: AtomicU32, +} +impl event::Subscriber for Subscriber +where + S::ConnectionContext: Recorder, +{ + type ConnectionContext = Context; + fn create_connection_context( + &self, + meta: &api::ConnectionMeta, + info: &api::ConnectionInfo, + ) -> Self::ConnectionContext { + Context { + recorder: self.subscriber.create_connection_context(meta, info), + application_write: AtomicU32::new(0), + application_read: AtomicU32::new(0), + } + } + #[inline] + fn on_application_write( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationWrite, + ) { + context.application_write.fetch_add(1, Ordering::Relaxed); + self.subscriber + .on_application_write(&context.recorder, meta, event); + } + #[inline] + fn on_application_read( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationRead, + ) { + context.application_read.fetch_add(1, Ordering::Relaxed); + self.subscriber + .on_application_read(&context.recorder, meta, event); + } +} +impl Drop for Context { + fn drop(&mut self) { + self.recorder.increment_counter( + "application_write", + self.application_write.load(Ordering::Relaxed) as _, + ); + self.recorder.increment_counter( + "application_read", + self.application_read.load(Ordering::Relaxed) as _, + ); + } +} diff --git a/dc/s2n-quic-dc/src/event/generated/metrics/aggregate.rs b/dc/s2n-quic-dc/src/event/generated/metrics/aggregate.rs new file mode 100644 index 000000000..230030549 --- /dev/null +++ b/dc/s2n-quic-dc/src/event/generated/metrics/aggregate.rs @@ -0,0 +1,582 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// DO NOT MODIFY THIS FILE +// This file was generated with the `s2n-quic-events` crate and any required +// changes should be made there. + +use crate::event::{ + self, api, + metrics::aggregate::{info, Info, Recorder, Registry}, +}; +const fn new_str(bytes: &'static str) -> info::Str<'static> { + unsafe { info::Str::new_unchecked(bytes) } +} +static INFO: &[Info; 26usize] = &[ + info::Builder { + id: 0usize, + name: new_str("application_write\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 1usize, + name: new_str("application_read\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 2usize, + name: new_str("endpoint_initialized\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 3usize, + name: new_str("path_secret_map_initialized\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 4usize, + name: new_str("path_secret_map_uninitialized\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 5usize, + name: new_str("path_secret_map_background_handshake_requested\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 6usize, + name: new_str("path_secret_map_entry_inserted\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 7usize, + name: new_str("path_secret_map_entry_ready\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 8usize, + name: new_str("path_secret_map_entry_replaced\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 9usize, + name: new_str("unknown_path_secret_packet_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 10usize, + name: new_str("unknown_path_secret_packet_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 11usize, + name: new_str("unknown_path_secret_packet_accepted\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 12usize, + name: new_str("unknown_path_secret_packet_rejected\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 13usize, + name: new_str("unknown_path_secret_packet_dropped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 14usize, + name: new_str("replay_definitely_detected\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 15usize, + name: new_str("replay_potentially_detected\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 16usize, + name: new_str("replay_detected_packet_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 17usize, + name: new_str("replay_detected_packet_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 18usize, + name: new_str("replay_detected_packet_accepted\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 19usize, + name: new_str("replay_detected_packet_rejected\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 20usize, + name: new_str("replay_detected_packet_dropped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 21usize, + name: new_str("stale_key_packet_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 22usize, + name: new_str("stale_key_packet_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 23usize, + name: new_str("stale_key_packet_accepted\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 24usize, + name: new_str("stale_key_packet_rejected\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 25usize, + name: new_str("stale_key_packet_dropped\0"), + units: new_str("\0"), + } + .build(), +]; +pub struct Subscriber { + #[allow(dead_code)] + counters: Box<[R::Counter]>, + #[allow(dead_code)] + measures: Box<[R::Measure]>, + #[allow(dead_code)] + gauges: Box<[R::Gauge]>, + #[allow(dead_code)] + timers: Box<[R::Timer]>, + #[allow(dead_code)] + registry: R, +} +impl Default for Subscriber { + fn default() -> Self { + Self::new(R::default()) + } +} +impl Subscriber { + #[doc = r" Creates a new subscriber with the given registry"] + #[doc = r""] + #[doc = r" # Note"] + #[doc = r""] + #[doc = r" All of the recorders are registered on initialization and cached for the lifetime"] + #[doc = r" of the subscriber."] + #[allow(unused_mut)] + #[inline] + pub fn new(registry: R) -> Self { + let mut counters = Vec::with_capacity(26usize); + let mut measures = Vec::with_capacity(0usize); + let mut gauges = Vec::with_capacity(0usize); + let mut timers = Vec::with_capacity(0usize); + counters.push(registry.register_counter(&INFO[0usize])); + counters.push(registry.register_counter(&INFO[1usize])); + counters.push(registry.register_counter(&INFO[2usize])); + counters.push(registry.register_counter(&INFO[3usize])); + counters.push(registry.register_counter(&INFO[4usize])); + counters.push(registry.register_counter(&INFO[5usize])); + counters.push(registry.register_counter(&INFO[6usize])); + counters.push(registry.register_counter(&INFO[7usize])); + counters.push(registry.register_counter(&INFO[8usize])); + counters.push(registry.register_counter(&INFO[9usize])); + counters.push(registry.register_counter(&INFO[10usize])); + counters.push(registry.register_counter(&INFO[11usize])); + counters.push(registry.register_counter(&INFO[12usize])); + counters.push(registry.register_counter(&INFO[13usize])); + counters.push(registry.register_counter(&INFO[14usize])); + counters.push(registry.register_counter(&INFO[15usize])); + counters.push(registry.register_counter(&INFO[16usize])); + counters.push(registry.register_counter(&INFO[17usize])); + counters.push(registry.register_counter(&INFO[18usize])); + counters.push(registry.register_counter(&INFO[19usize])); + counters.push(registry.register_counter(&INFO[20usize])); + counters.push(registry.register_counter(&INFO[21usize])); + counters.push(registry.register_counter(&INFO[22usize])); + counters.push(registry.register_counter(&INFO[23usize])); + counters.push(registry.register_counter(&INFO[24usize])); + counters.push(registry.register_counter(&INFO[25usize])); + Self { + counters: counters.into(), + measures: measures.into(), + gauges: gauges.into(), + timers: timers.into(), + registry, + } + } + #[doc = r" Returns all of the registered counters"] + #[inline] + pub fn counters(&self) -> impl Iterator + '_ { + self.counters + .iter() + .enumerate() + .map(|(idx, entry)| match idx { + 0usize => (&INFO[0usize], entry), + 1usize => (&INFO[1usize], entry), + 2usize => (&INFO[2usize], entry), + 3usize => (&INFO[3usize], entry), + 4usize => (&INFO[4usize], entry), + 5usize => (&INFO[5usize], entry), + 6usize => (&INFO[6usize], entry), + 7usize => (&INFO[7usize], entry), + 8usize => (&INFO[8usize], entry), + 9usize => (&INFO[9usize], entry), + 10usize => (&INFO[10usize], entry), + 11usize => (&INFO[11usize], entry), + 12usize => (&INFO[12usize], entry), + 13usize => (&INFO[13usize], entry), + 14usize => (&INFO[14usize], entry), + 15usize => (&INFO[15usize], entry), + 16usize => (&INFO[16usize], entry), + 17usize => (&INFO[17usize], entry), + 18usize => (&INFO[18usize], entry), + 19usize => (&INFO[19usize], entry), + 20usize => (&INFO[20usize], entry), + 21usize => (&INFO[21usize], entry), + 22usize => (&INFO[22usize], entry), + 23usize => (&INFO[23usize], entry), + 24usize => (&INFO[24usize], entry), + 25usize => (&INFO[25usize], entry), + _ => unsafe { core::hint::unreachable_unchecked() }, + }) + } + #[allow(dead_code)] + #[inline(always)] + fn count(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let counter = unsafe { self.counters.get_unchecked(id) }; + counter.record(info, value); + } + #[doc = r" Returns all of the registered measures"] + #[inline] + pub fn measures(&self) -> impl Iterator + '_ { + core::iter::empty() + } + #[allow(dead_code)] + #[inline(always)] + fn measure(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let measure = unsafe { self.measures.get_unchecked(id) }; + measure.record(info, value); + } + #[doc = r" Returns all of the registered gauges"] + #[inline] + pub fn gauges(&self) -> impl Iterator + '_ { + core::iter::empty() + } + #[allow(dead_code)] + #[inline(always)] + fn gauge(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let gauge = unsafe { self.gauges.get_unchecked(id) }; + gauge.record(info, value); + } + #[doc = r" Returns all of the registered timers"] + #[inline] + pub fn timers(&self) -> impl Iterator + '_ { + core::iter::empty() + } + #[allow(dead_code)] + #[inline(always)] + fn time(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let timer = unsafe { self.timers.get_unchecked(id) }; + timer.record(info, value); + } +} +impl event::Subscriber for Subscriber { + type ConnectionContext = (); + fn create_connection_context( + &self, + _meta: &api::ConnectionMeta, + _info: &api::ConnectionInfo, + ) -> Self::ConnectionContext { + } + #[inline] + fn on_application_write( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationWrite, + ) { + self.count(0usize, 0usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_application_read( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationRead, + ) { + self.count(1usize, 1usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_endpoint_initialized(&self, meta: &api::EndpointMeta, event: &api::EndpointInitialized) { + self.count(2usize, 2usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_path_secret_map_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapInitialized, + ) { + self.count(3usize, 3usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_path_secret_map_uninitialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapUninitialized, + ) { + self.count(4usize, 4usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_path_secret_map_background_handshake_requested( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapBackgroundHandshakeRequested, + ) { + self.count(5usize, 5usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_path_secret_map_entry_inserted( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryInserted, + ) { + self.count(6usize, 6usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_path_secret_map_entry_ready( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReady, + ) { + self.count(7usize, 7usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_path_secret_map_entry_replaced( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReplaced, + ) { + self.count(8usize, 8usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_unknown_path_secret_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketSent, + ) { + self.count(9usize, 9usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_unknown_path_secret_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketReceived, + ) { + self.count(10usize, 10usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_unknown_path_secret_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketAccepted, + ) { + self.count(11usize, 11usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_unknown_path_secret_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketRejected, + ) { + self.count(12usize, 12usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_unknown_path_secret_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketDropped, + ) { + self.count(13usize, 13usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_definitely_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDefinitelyDetected, + ) { + self.count(14usize, 14usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_potentially_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayPotentiallyDetected, + ) { + self.count(15usize, 15usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_detected_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketSent, + ) { + self.count(16usize, 16usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_detected_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketReceived, + ) { + self.count(17usize, 17usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_detected_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketAccepted, + ) { + self.count(18usize, 18usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_detected_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketRejected, + ) { + self.count(19usize, 19usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_replay_detected_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketDropped, + ) { + self.count(20usize, 20usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_stale_key_packet_sent(&self, meta: &api::EndpointMeta, event: &api::StaleKeyPacketSent) { + self.count(21usize, 21usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_stale_key_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketReceived, + ) { + self.count(22usize, 22usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_stale_key_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketAccepted, + ) { + self.count(23usize, 23usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_stale_key_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketRejected, + ) { + self.count(24usize, 24usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_stale_key_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketDropped, + ) { + self.count(25usize, 25usize, 1); + let _ = event; + let _ = meta; + } +} diff --git a/dc/s2n-quic-dc/src/event/generated/metrics/probe.rs b/dc/s2n-quic-dc/src/event/generated/metrics/probe.rs new file mode 100644 index 000000000..a06701737 --- /dev/null +++ b/dc/s2n-quic-dc/src/event/generated/metrics/probe.rs @@ -0,0 +1,173 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// DO NOT MODIFY THIS FILE +// This file was generated with the `s2n-quic-events` crate and any required +// changes should be made there. + +use crate::event::metrics::aggregate::{self, Info, Recorder}; +use s2n_quic_core::probe::define; +mod counter { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + match info.id { + 0usize => Self(application_write), + 1usize => Self(application_read), + 2usize => Self(endpoint_initialized), + 3usize => Self(path_secret_map_initialized), + 4usize => Self(path_secret_map_uninitialized), + 5usize => Self(path_secret_map_background_handshake_requested), + 6usize => Self(path_secret_map_entry_inserted), + 7usize => Self(path_secret_map_entry_ready), + 8usize => Self(path_secret_map_entry_replaced), + 9usize => Self(unknown_path_secret_packet_sent), + 10usize => Self(unknown_path_secret_packet_received), + 11usize => Self(unknown_path_secret_packet_accepted), + 12usize => Self(unknown_path_secret_packet_rejected), + 13usize => Self(unknown_path_secret_packet_dropped), + 14usize => Self(replay_definitely_detected), + 15usize => Self(replay_potentially_detected), + 16usize => Self(replay_detected_packet_sent), + 17usize => Self(replay_detected_packet_received), + 18usize => Self(replay_detected_packet_accepted), + 19usize => Self(replay_detected_packet_rejected), + 20usize => Self(replay_detected_packet_dropped), + 21usize => Self(stale_key_packet_sent), + 22usize => Self(stale_key_packet_received), + 23usize => Self(stale_key_packet_accepted), + 24usize => Self(stale_key_packet_rejected), + 25usize => Self(stale_key_packet_dropped), + _ => unreachable!("invalid info: {info:?}"), + } + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } + super::define!( + extern "probe" { + # [link_name = s2n_quic_dc__event__counter__application_write] + fn application_write(value: u64); + # [link_name = s2n_quic_dc__event__counter__application_read] + fn application_read(value: u64); + # [link_name = s2n_quic_dc__event__counter__endpoint_initialized] + fn endpoint_initialized(value: u64); + # [link_name = s2n_quic_dc__event__counter__path_secret_map_initialized] + fn path_secret_map_initialized(value: u64); + # [link_name = s2n_quic_dc__event__counter__path_secret_map_uninitialized] + fn path_secret_map_uninitialized(value: u64); + # [link_name = s2n_quic_dc__event__counter__path_secret_map_background_handshake_requested] + fn path_secret_map_background_handshake_requested(value: u64); + # [link_name = s2n_quic_dc__event__counter__path_secret_map_entry_inserted] + fn path_secret_map_entry_inserted(value: u64); + # [link_name = s2n_quic_dc__event__counter__path_secret_map_entry_ready] + fn path_secret_map_entry_ready(value: u64); + # [link_name = s2n_quic_dc__event__counter__path_secret_map_entry_replaced] + fn path_secret_map_entry_replaced(value: u64); + # [link_name = s2n_quic_dc__event__counter__unknown_path_secret_packet_sent] + fn unknown_path_secret_packet_sent(value: u64); + # [link_name = s2n_quic_dc__event__counter__unknown_path_secret_packet_received] + fn unknown_path_secret_packet_received(value: u64); + # [link_name = s2n_quic_dc__event__counter__unknown_path_secret_packet_accepted] + fn unknown_path_secret_packet_accepted(value: u64); + # [link_name = s2n_quic_dc__event__counter__unknown_path_secret_packet_rejected] + fn unknown_path_secret_packet_rejected(value: u64); + # [link_name = s2n_quic_dc__event__counter__unknown_path_secret_packet_dropped] + fn unknown_path_secret_packet_dropped(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_definitely_detected] + fn replay_definitely_detected(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_potentially_detected] + fn replay_potentially_detected(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_detected_packet_sent] + fn replay_detected_packet_sent(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_detected_packet_received] + fn replay_detected_packet_received(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_detected_packet_accepted] + fn replay_detected_packet_accepted(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_detected_packet_rejected] + fn replay_detected_packet_rejected(value: u64); + # [link_name = s2n_quic_dc__event__counter__replay_detected_packet_dropped] + fn replay_detected_packet_dropped(value: u64); + # [link_name = s2n_quic_dc__event__counter__stale_key_packet_sent] + fn stale_key_packet_sent(value: u64); + # [link_name = s2n_quic_dc__event__counter__stale_key_packet_received] + fn stale_key_packet_received(value: u64); + # [link_name = s2n_quic_dc__event__counter__stale_key_packet_accepted] + fn stale_key_packet_accepted(value: u64); + # [link_name = s2n_quic_dc__event__counter__stale_key_packet_rejected] + fn stale_key_packet_rejected(value: u64); + # [link_name = s2n_quic_dc__event__counter__stale_key_packet_dropped] + fn stale_key_packet_dropped(value: u64); + } + ); +} +mod measure { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + unreachable!("invalid info: {info:?}") + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } +} +mod gauge { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + unreachable!("invalid info: {info:?}") + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } +} +mod timer { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + unreachable!("invalid info: {info:?}") + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } +} +#[derive(Default)] +pub struct Registry(()); +impl aggregate::Registry for Registry { + type Counter = counter::Recorder; + type Measure = measure::Recorder; + type Gauge = gauge::Recorder; + type Timer = timer::Recorder; + #[inline] + fn register_counter(&self, info: &'static Info) -> Self::Counter { + counter::Recorder::new(info) + } + #[inline] + fn register_measure(&self, info: &'static Info) -> Self::Measure { + measure::Recorder::new(info) + } + #[inline] + fn register_gauge(&self, info: &'static Info) -> Self::Gauge { + gauge::Recorder::new(info) + } + #[inline] + fn register_timer(&self, info: &'static Info) -> Self::Timer { + timer::Recorder::new(info) + } +} diff --git a/dc/s2n-quic-dc/src/path/secret/map/event_tests.rs b/dc/s2n-quic-dc/src/path/secret/map/event_tests.rs index 0c7c8177d..2c2fa405d 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/event_tests.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/event_tests.rs @@ -2,16 +2,26 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - event::testing::Subscriber, + event, packet::{secret_control as control, WireVersion}, path::secret::{stateless_reset, Map}, }; use s2n_codec::{DecoderBufferMut, EncoderBuffer}; use std::sync::Arc; +type Subscriber = ( + event::testing::Subscriber, + event::metrics::aggregate::Subscriber<( + event::metrics::aggregate::probe::Registry, + event::metrics::aggregate::probe::dynamic::Registry, + )>, +); + #[track_caller] fn sub() -> Arc { - Arc::new(Subscriber::snapshot()) + crate::testing::init_tracing(); + + Arc::new((event::testing::Subscriber::snapshot(), Default::default())) } #[track_caller] @@ -21,6 +31,7 @@ fn map(capacity: usize) -> Map { fn map_sub(capacity: usize, sub: Arc) -> Map { let signer = stateless_reset::Signer::random(); + Map::new(signer, capacity, sub) } diff --git a/dc/s2n-quic-dc/src/testing.rs b/dc/s2n-quic-dc/src/testing.rs index 93775f5ff..93e057ece 100644 --- a/dc/s2n-quic-dc/src/testing.rs +++ b/dc/s2n-quic-dc/src/testing.rs @@ -7,3 +7,29 @@ pub fn assert_sync(_v: &T) {} pub fn assert_static(_v: &T) {} pub fn assert_async_read(_v: &T) {} pub fn assert_async_write(_v: &T) {} + +pub fn init_tracing() { + use std::sync::Once; + + static TRACING: Once = Once::new(); + + // make sure this only gets initialized once + TRACING.call_once(|| { + let format = tracing_subscriber::fmt::format() + //.with_level(false) // don't include levels in formatted output + //.with_ansi(false) + .compact(); // Use a less verbose output format. + + let env_filter = tracing_subscriber::EnvFilter::builder() + .with_default_directive(tracing::Level::DEBUG.into()) + .with_env_var("S2N_LOG") + .from_env() + .unwrap(); + + tracing_subscriber::fmt() + .with_env_filter(env_filter) + .event_format(format) + .with_test_writer() + .init(); + }); +} diff --git a/quic/s2n-quic-core/src/event/generated.rs b/quic/s2n-quic-core/src/event/generated.rs index 2fd6ff90d..d59a19308 100644 --- a/quic/s2n-quic-core/src/event/generated.rs +++ b/quic/s2n-quic-core/src/event/generated.rs @@ -6,6 +6,7 @@ // changes should be made there. use super::*; +pub(crate) mod metrics; pub mod api { #![doc = r" This module contains events that are emitted to the [`Subscriber`](crate::event::Subscriber)"] use super::*; @@ -7599,703 +7600,6 @@ mod traits { } } } -pub mod metrics { - use super::*; - use crate::event::metrics::Recorder; - #[derive(Debug)] - pub struct Subscriber - where - S::ConnectionContext: Recorder, - { - subscriber: S, - } - impl Subscriber - where - S::ConnectionContext: Recorder, - { - pub fn new(subscriber: S) -> Self { - Self { subscriber } - } - } - pub struct Context { - recorder: R, - application_protocol_information: u32, - server_name_information: u32, - packet_skipped: u32, - packet_sent: u32, - packet_received: u32, - active_path_updated: u32, - path_created: u32, - frame_sent: u32, - frame_received: u32, - packet_lost: u32, - recovery_metrics: u32, - congestion: u32, - ack_processed: u32, - rx_ack_range_dropped: u32, - ack_range_received: u32, - ack_range_sent: u32, - packet_dropped: u32, - key_update: u32, - key_space_discarded: u32, - connection_started: u32, - connection_closed: u32, - duplicate_packet: u32, - transport_parameters_received: u32, - datagram_sent: u32, - datagram_received: u32, - datagram_dropped: u32, - connection_id_updated: u32, - ecn_state_changed: u32, - connection_migration_denied: u32, - handshake_status_updated: u32, - tls_exporter_ready: u32, - path_challenge_updated: u32, - tls_client_hello: u32, - tls_server_hello: u32, - rx_stream_progress: u32, - tx_stream_progress: u32, - keep_alive_timer_expired: u32, - mtu_updated: u32, - slow_start_exited: u32, - delivery_rate_sampled: u32, - pacing_rate_updated: u32, - bbr_state_changed: u32, - dc_state_changed: u32, - } - impl super::Subscriber for Subscriber - where - S::ConnectionContext: Recorder, - { - type ConnectionContext = Context; - fn create_connection_context( - &mut self, - meta: &api::ConnectionMeta, - info: &api::ConnectionInfo, - ) -> Self::ConnectionContext { - Context { - recorder: self.subscriber.create_connection_context(meta, info), - application_protocol_information: 0, - server_name_information: 0, - packet_skipped: 0, - packet_sent: 0, - packet_received: 0, - active_path_updated: 0, - path_created: 0, - frame_sent: 0, - frame_received: 0, - packet_lost: 0, - recovery_metrics: 0, - congestion: 0, - ack_processed: 0, - rx_ack_range_dropped: 0, - ack_range_received: 0, - ack_range_sent: 0, - packet_dropped: 0, - key_update: 0, - key_space_discarded: 0, - connection_started: 0, - connection_closed: 0, - duplicate_packet: 0, - transport_parameters_received: 0, - datagram_sent: 0, - datagram_received: 0, - datagram_dropped: 0, - connection_id_updated: 0, - ecn_state_changed: 0, - connection_migration_denied: 0, - handshake_status_updated: 0, - tls_exporter_ready: 0, - path_challenge_updated: 0, - tls_client_hello: 0, - tls_server_hello: 0, - rx_stream_progress: 0, - tx_stream_progress: 0, - keep_alive_timer_expired: 0, - mtu_updated: 0, - slow_start_exited: 0, - delivery_rate_sampled: 0, - pacing_rate_updated: 0, - bbr_state_changed: 0, - dc_state_changed: 0, - } - } - #[inline] - fn on_application_protocol_information( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ApplicationProtocolInformation, - ) { - context.application_protocol_information += 1; - self.subscriber - .on_application_protocol_information(&mut context.recorder, meta, event); - } - #[inline] - fn on_server_name_information( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ServerNameInformation, - ) { - context.server_name_information += 1; - self.subscriber - .on_server_name_information(&mut context.recorder, meta, event); - } - #[inline] - fn on_packet_skipped( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PacketSkipped, - ) { - context.packet_skipped += 1; - self.subscriber - .on_packet_skipped(&mut context.recorder, meta, event); - } - #[inline] - fn on_packet_sent( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PacketSent, - ) { - context.packet_sent += 1; - self.subscriber - .on_packet_sent(&mut context.recorder, meta, event); - } - #[inline] - fn on_packet_received( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PacketReceived, - ) { - context.packet_received += 1; - self.subscriber - .on_packet_received(&mut context.recorder, meta, event); - } - #[inline] - fn on_active_path_updated( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ActivePathUpdated, - ) { - context.active_path_updated += 1; - self.subscriber - .on_active_path_updated(&mut context.recorder, meta, event); - } - #[inline] - fn on_path_created( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PathCreated, - ) { - context.path_created += 1; - self.subscriber - .on_path_created(&mut context.recorder, meta, event); - } - #[inline] - fn on_frame_sent( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::FrameSent, - ) { - context.frame_sent += 1; - self.subscriber - .on_frame_sent(&mut context.recorder, meta, event); - } - #[inline] - fn on_frame_received( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::FrameReceived, - ) { - context.frame_received += 1; - self.subscriber - .on_frame_received(&mut context.recorder, meta, event); - } - #[inline] - fn on_packet_lost( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PacketLost, - ) { - context.packet_lost += 1; - self.subscriber - .on_packet_lost(&mut context.recorder, meta, event); - } - #[inline] - fn on_recovery_metrics( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::RecoveryMetrics, - ) { - context.recovery_metrics += 1; - self.subscriber - .on_recovery_metrics(&mut context.recorder, meta, event); - } - #[inline] - fn on_congestion( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::Congestion, - ) { - context.congestion += 1; - self.subscriber - .on_congestion(&mut context.recorder, meta, event); - } - #[inline] - #[allow(deprecated)] - fn on_ack_processed( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::AckProcessed, - ) { - context.ack_processed += 1; - self.subscriber - .on_ack_processed(&mut context.recorder, meta, event); - } - #[inline] - fn on_rx_ack_range_dropped( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::RxAckRangeDropped, - ) { - context.rx_ack_range_dropped += 1; - self.subscriber - .on_rx_ack_range_dropped(&mut context.recorder, meta, event); - } - #[inline] - fn on_ack_range_received( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::AckRangeReceived, - ) { - context.ack_range_received += 1; - self.subscriber - .on_ack_range_received(&mut context.recorder, meta, event); - } - #[inline] - fn on_ack_range_sent( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::AckRangeSent, - ) { - context.ack_range_sent += 1; - self.subscriber - .on_ack_range_sent(&mut context.recorder, meta, event); - } - #[inline] - fn on_packet_dropped( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PacketDropped, - ) { - context.packet_dropped += 1; - self.subscriber - .on_packet_dropped(&mut context.recorder, meta, event); - } - #[inline] - fn on_key_update( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::KeyUpdate, - ) { - context.key_update += 1; - self.subscriber - .on_key_update(&mut context.recorder, meta, event); - } - #[inline] - fn on_key_space_discarded( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::KeySpaceDiscarded, - ) { - context.key_space_discarded += 1; - self.subscriber - .on_key_space_discarded(&mut context.recorder, meta, event); - } - #[inline] - fn on_connection_started( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ConnectionStarted, - ) { - context.connection_started += 1; - self.subscriber - .on_connection_started(&mut context.recorder, meta, event); - } - #[inline] - fn on_connection_closed( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ConnectionClosed, - ) { - context.connection_closed += 1; - self.subscriber - .on_connection_closed(&mut context.recorder, meta, event); - } - #[inline] - fn on_duplicate_packet( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::DuplicatePacket, - ) { - context.duplicate_packet += 1; - self.subscriber - .on_duplicate_packet(&mut context.recorder, meta, event); - } - #[inline] - fn on_transport_parameters_received( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::TransportParametersReceived, - ) { - context.transport_parameters_received += 1; - self.subscriber - .on_transport_parameters_received(&mut context.recorder, meta, event); - } - #[inline] - fn on_datagram_sent( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::DatagramSent, - ) { - context.datagram_sent += 1; - self.subscriber - .on_datagram_sent(&mut context.recorder, meta, event); - } - #[inline] - fn on_datagram_received( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::DatagramReceived, - ) { - context.datagram_received += 1; - self.subscriber - .on_datagram_received(&mut context.recorder, meta, event); - } - #[inline] - fn on_datagram_dropped( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::DatagramDropped, - ) { - context.datagram_dropped += 1; - self.subscriber - .on_datagram_dropped(&mut context.recorder, meta, event); - } - #[inline] - fn on_connection_id_updated( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ConnectionIdUpdated, - ) { - context.connection_id_updated += 1; - self.subscriber - .on_connection_id_updated(&mut context.recorder, meta, event); - } - #[inline] - fn on_ecn_state_changed( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::EcnStateChanged, - ) { - context.ecn_state_changed += 1; - self.subscriber - .on_ecn_state_changed(&mut context.recorder, meta, event); - } - #[inline] - fn on_connection_migration_denied( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ConnectionMigrationDenied, - ) { - context.connection_migration_denied += 1; - self.subscriber - .on_connection_migration_denied(&mut context.recorder, meta, event); - } - #[inline] - fn on_handshake_status_updated( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::HandshakeStatusUpdated, - ) { - context.handshake_status_updated += 1; - self.subscriber - .on_handshake_status_updated(&mut context.recorder, meta, event); - } - #[inline] - fn on_tls_exporter_ready( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::TlsExporterReady, - ) { - context.tls_exporter_ready += 1; - self.subscriber - .on_tls_exporter_ready(&mut context.recorder, meta, event); - } - #[inline] - fn on_path_challenge_updated( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PathChallengeUpdated, - ) { - context.path_challenge_updated += 1; - self.subscriber - .on_path_challenge_updated(&mut context.recorder, meta, event); - } - #[inline] - fn on_tls_client_hello( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::TlsClientHello, - ) { - context.tls_client_hello += 1; - self.subscriber - .on_tls_client_hello(&mut context.recorder, meta, event); - } - #[inline] - fn on_tls_server_hello( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::TlsServerHello, - ) { - context.tls_server_hello += 1; - self.subscriber - .on_tls_server_hello(&mut context.recorder, meta, event); - } - #[inline] - fn on_rx_stream_progress( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::RxStreamProgress, - ) { - context.rx_stream_progress += 1; - self.subscriber - .on_rx_stream_progress(&mut context.recorder, meta, event); - } - #[inline] - fn on_tx_stream_progress( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::TxStreamProgress, - ) { - context.tx_stream_progress += 1; - self.subscriber - .on_tx_stream_progress(&mut context.recorder, meta, event); - } - #[inline] - fn on_keep_alive_timer_expired( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::KeepAliveTimerExpired, - ) { - context.keep_alive_timer_expired += 1; - self.subscriber - .on_keep_alive_timer_expired(&mut context.recorder, meta, event); - } - #[inline] - fn on_mtu_updated( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::MtuUpdated, - ) { - context.mtu_updated += 1; - self.subscriber - .on_mtu_updated(&mut context.recorder, meta, event); - } - #[inline] - fn on_slow_start_exited( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::SlowStartExited, - ) { - context.slow_start_exited += 1; - self.subscriber - .on_slow_start_exited(&mut context.recorder, meta, event); - } - #[inline] - fn on_delivery_rate_sampled( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::DeliveryRateSampled, - ) { - context.delivery_rate_sampled += 1; - self.subscriber - .on_delivery_rate_sampled(&mut context.recorder, meta, event); - } - #[inline] - fn on_pacing_rate_updated( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::PacingRateUpdated, - ) { - context.pacing_rate_updated += 1; - self.subscriber - .on_pacing_rate_updated(&mut context.recorder, meta, event); - } - #[inline] - fn on_bbr_state_changed( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::BbrStateChanged, - ) { - context.bbr_state_changed += 1; - self.subscriber - .on_bbr_state_changed(&mut context.recorder, meta, event); - } - #[inline] - fn on_dc_state_changed( - &mut self, - context: &mut Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::DcStateChanged, - ) { - context.dc_state_changed += 1; - self.subscriber - .on_dc_state_changed(&mut context.recorder, meta, event); - } - } - impl Drop for Context { - fn drop(&mut self) { - self.recorder.increment_counter( - "application_protocol_information", - self.application_protocol_information as _, - ); - self.recorder - .increment_counter("server_name_information", self.server_name_information as _); - self.recorder - .increment_counter("packet_skipped", self.packet_skipped as _); - self.recorder - .increment_counter("packet_sent", self.packet_sent as _); - self.recorder - .increment_counter("packet_received", self.packet_received as _); - self.recorder - .increment_counter("active_path_updated", self.active_path_updated as _); - self.recorder - .increment_counter("path_created", self.path_created as _); - self.recorder - .increment_counter("frame_sent", self.frame_sent as _); - self.recorder - .increment_counter("frame_received", self.frame_received as _); - self.recorder - .increment_counter("packet_lost", self.packet_lost as _); - self.recorder - .increment_counter("recovery_metrics", self.recovery_metrics as _); - self.recorder - .increment_counter("congestion", self.congestion as _); - self.recorder - .increment_counter("ack_processed", self.ack_processed as _); - self.recorder - .increment_counter("rx_ack_range_dropped", self.rx_ack_range_dropped as _); - self.recorder - .increment_counter("ack_range_received", self.ack_range_received as _); - self.recorder - .increment_counter("ack_range_sent", self.ack_range_sent as _); - self.recorder - .increment_counter("packet_dropped", self.packet_dropped as _); - self.recorder - .increment_counter("key_update", self.key_update as _); - self.recorder - .increment_counter("key_space_discarded", self.key_space_discarded as _); - self.recorder - .increment_counter("connection_started", self.connection_started as _); - self.recorder - .increment_counter("connection_closed", self.connection_closed as _); - self.recorder - .increment_counter("duplicate_packet", self.duplicate_packet as _); - self.recorder.increment_counter( - "transport_parameters_received", - self.transport_parameters_received as _, - ); - self.recorder - .increment_counter("datagram_sent", self.datagram_sent as _); - self.recorder - .increment_counter("datagram_received", self.datagram_received as _); - self.recorder - .increment_counter("datagram_dropped", self.datagram_dropped as _); - self.recorder - .increment_counter("connection_id_updated", self.connection_id_updated as _); - self.recorder - .increment_counter("ecn_state_changed", self.ecn_state_changed as _); - self.recorder.increment_counter( - "connection_migration_denied", - self.connection_migration_denied as _, - ); - self.recorder.increment_counter( - "handshake_status_updated", - self.handshake_status_updated as _, - ); - self.recorder - .increment_counter("tls_exporter_ready", self.tls_exporter_ready as _); - self.recorder - .increment_counter("path_challenge_updated", self.path_challenge_updated as _); - self.recorder - .increment_counter("tls_client_hello", self.tls_client_hello as _); - self.recorder - .increment_counter("tls_server_hello", self.tls_server_hello as _); - self.recorder - .increment_counter("rx_stream_progress", self.rx_stream_progress as _); - self.recorder - .increment_counter("tx_stream_progress", self.tx_stream_progress as _); - self.recorder.increment_counter( - "keep_alive_timer_expired", - self.keep_alive_timer_expired as _, - ); - self.recorder - .increment_counter("mtu_updated", self.mtu_updated as _); - self.recorder - .increment_counter("slow_start_exited", self.slow_start_exited as _); - self.recorder - .increment_counter("delivery_rate_sampled", self.delivery_rate_sampled as _); - self.recorder - .increment_counter("pacing_rate_updated", self.pacing_rate_updated as _); - self.recorder - .increment_counter("bbr_state_changed", self.bbr_state_changed as _); - self.recorder - .increment_counter("dc_state_changed", self.dc_state_changed as _); - } - } -} #[cfg(any(test, feature = "testing"))] pub mod testing { use super::*; diff --git a/quic/s2n-quic-core/src/event/generated/metrics.rs b/quic/s2n-quic-core/src/event/generated/metrics.rs new file mode 100644 index 000000000..7c6139d48 --- /dev/null +++ b/quic/s2n-quic-core/src/event/generated/metrics.rs @@ -0,0 +1,704 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// DO NOT MODIFY THIS FILE +// This file was generated with the `s2n-quic-events` crate and any required +// changes should be made there. + +use crate::event::{self, api, metrics::Recorder}; +#[cfg(feature = "alloc")] +pub(crate) mod aggregate; +pub(crate) mod probe; +#[derive(Debug)] +pub struct Subscriber +where + S::ConnectionContext: Recorder, +{ + subscriber: S, +} +impl Subscriber +where + S::ConnectionContext: Recorder, +{ + pub fn new(subscriber: S) -> Self { + Self { subscriber } + } +} +pub struct Context { + recorder: R, + application_protocol_information: u32, + server_name_information: u32, + packet_skipped: u32, + packet_sent: u32, + packet_received: u32, + active_path_updated: u32, + path_created: u32, + frame_sent: u32, + frame_received: u32, + packet_lost: u32, + recovery_metrics: u32, + congestion: u32, + ack_processed: u32, + rx_ack_range_dropped: u32, + ack_range_received: u32, + ack_range_sent: u32, + packet_dropped: u32, + key_update: u32, + key_space_discarded: u32, + connection_started: u32, + connection_closed: u32, + duplicate_packet: u32, + transport_parameters_received: u32, + datagram_sent: u32, + datagram_received: u32, + datagram_dropped: u32, + connection_id_updated: u32, + ecn_state_changed: u32, + connection_migration_denied: u32, + handshake_status_updated: u32, + tls_exporter_ready: u32, + path_challenge_updated: u32, + tls_client_hello: u32, + tls_server_hello: u32, + rx_stream_progress: u32, + tx_stream_progress: u32, + keep_alive_timer_expired: u32, + mtu_updated: u32, + slow_start_exited: u32, + delivery_rate_sampled: u32, + pacing_rate_updated: u32, + bbr_state_changed: u32, + dc_state_changed: u32, +} +impl event::Subscriber for Subscriber +where + S::ConnectionContext: Recorder, +{ + type ConnectionContext = Context; + fn create_connection_context( + &mut self, + meta: &api::ConnectionMeta, + info: &api::ConnectionInfo, + ) -> Self::ConnectionContext { + Context { + recorder: self.subscriber.create_connection_context(meta, info), + application_protocol_information: 0, + server_name_information: 0, + packet_skipped: 0, + packet_sent: 0, + packet_received: 0, + active_path_updated: 0, + path_created: 0, + frame_sent: 0, + frame_received: 0, + packet_lost: 0, + recovery_metrics: 0, + congestion: 0, + ack_processed: 0, + rx_ack_range_dropped: 0, + ack_range_received: 0, + ack_range_sent: 0, + packet_dropped: 0, + key_update: 0, + key_space_discarded: 0, + connection_started: 0, + connection_closed: 0, + duplicate_packet: 0, + transport_parameters_received: 0, + datagram_sent: 0, + datagram_received: 0, + datagram_dropped: 0, + connection_id_updated: 0, + ecn_state_changed: 0, + connection_migration_denied: 0, + handshake_status_updated: 0, + tls_exporter_ready: 0, + path_challenge_updated: 0, + tls_client_hello: 0, + tls_server_hello: 0, + rx_stream_progress: 0, + tx_stream_progress: 0, + keep_alive_timer_expired: 0, + mtu_updated: 0, + slow_start_exited: 0, + delivery_rate_sampled: 0, + pacing_rate_updated: 0, + bbr_state_changed: 0, + dc_state_changed: 0, + } + } + #[inline] + fn on_application_protocol_information( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationProtocolInformation, + ) { + context.application_protocol_information += 1; + self.subscriber + .on_application_protocol_information(&mut context.recorder, meta, event); + } + #[inline] + fn on_server_name_information( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ServerNameInformation, + ) { + context.server_name_information += 1; + self.subscriber + .on_server_name_information(&mut context.recorder, meta, event); + } + #[inline] + fn on_packet_skipped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketSkipped, + ) { + context.packet_skipped += 1; + self.subscriber + .on_packet_skipped(&mut context.recorder, meta, event); + } + #[inline] + fn on_packet_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketSent, + ) { + context.packet_sent += 1; + self.subscriber + .on_packet_sent(&mut context.recorder, meta, event); + } + #[inline] + fn on_packet_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketReceived, + ) { + context.packet_received += 1; + self.subscriber + .on_packet_received(&mut context.recorder, meta, event); + } + #[inline] + fn on_active_path_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ActivePathUpdated, + ) { + context.active_path_updated += 1; + self.subscriber + .on_active_path_updated(&mut context.recorder, meta, event); + } + #[inline] + fn on_path_created( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PathCreated, + ) { + context.path_created += 1; + self.subscriber + .on_path_created(&mut context.recorder, meta, event); + } + #[inline] + fn on_frame_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::FrameSent, + ) { + context.frame_sent += 1; + self.subscriber + .on_frame_sent(&mut context.recorder, meta, event); + } + #[inline] + fn on_frame_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::FrameReceived, + ) { + context.frame_received += 1; + self.subscriber + .on_frame_received(&mut context.recorder, meta, event); + } + #[inline] + fn on_packet_lost( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketLost, + ) { + context.packet_lost += 1; + self.subscriber + .on_packet_lost(&mut context.recorder, meta, event); + } + #[inline] + fn on_recovery_metrics( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::RecoveryMetrics, + ) { + context.recovery_metrics += 1; + self.subscriber + .on_recovery_metrics(&mut context.recorder, meta, event); + } + #[inline] + fn on_congestion( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::Congestion, + ) { + context.congestion += 1; + self.subscriber + .on_congestion(&mut context.recorder, meta, event); + } + #[inline] + #[allow(deprecated)] + fn on_ack_processed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::AckProcessed, + ) { + context.ack_processed += 1; + self.subscriber + .on_ack_processed(&mut context.recorder, meta, event); + } + #[inline] + fn on_rx_ack_range_dropped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::RxAckRangeDropped, + ) { + context.rx_ack_range_dropped += 1; + self.subscriber + .on_rx_ack_range_dropped(&mut context.recorder, meta, event); + } + #[inline] + fn on_ack_range_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::AckRangeReceived, + ) { + context.ack_range_received += 1; + self.subscriber + .on_ack_range_received(&mut context.recorder, meta, event); + } + #[inline] + fn on_ack_range_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::AckRangeSent, + ) { + context.ack_range_sent += 1; + self.subscriber + .on_ack_range_sent(&mut context.recorder, meta, event); + } + #[inline] + fn on_packet_dropped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketDropped, + ) { + context.packet_dropped += 1; + self.subscriber + .on_packet_dropped(&mut context.recorder, meta, event); + } + #[inline] + fn on_key_update( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::KeyUpdate, + ) { + context.key_update += 1; + self.subscriber + .on_key_update(&mut context.recorder, meta, event); + } + #[inline] + fn on_key_space_discarded( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::KeySpaceDiscarded, + ) { + context.key_space_discarded += 1; + self.subscriber + .on_key_space_discarded(&mut context.recorder, meta, event); + } + #[inline] + fn on_connection_started( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionStarted, + ) { + context.connection_started += 1; + self.subscriber + .on_connection_started(&mut context.recorder, meta, event); + } + #[inline] + fn on_connection_closed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionClosed, + ) { + context.connection_closed += 1; + self.subscriber + .on_connection_closed(&mut context.recorder, meta, event); + } + #[inline] + fn on_duplicate_packet( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DuplicatePacket, + ) { + context.duplicate_packet += 1; + self.subscriber + .on_duplicate_packet(&mut context.recorder, meta, event); + } + #[inline] + fn on_transport_parameters_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TransportParametersReceived, + ) { + context.transport_parameters_received += 1; + self.subscriber + .on_transport_parameters_received(&mut context.recorder, meta, event); + } + #[inline] + fn on_datagram_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DatagramSent, + ) { + context.datagram_sent += 1; + self.subscriber + .on_datagram_sent(&mut context.recorder, meta, event); + } + #[inline] + fn on_datagram_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DatagramReceived, + ) { + context.datagram_received += 1; + self.subscriber + .on_datagram_received(&mut context.recorder, meta, event); + } + #[inline] + fn on_datagram_dropped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DatagramDropped, + ) { + context.datagram_dropped += 1; + self.subscriber + .on_datagram_dropped(&mut context.recorder, meta, event); + } + #[inline] + fn on_connection_id_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionIdUpdated, + ) { + context.connection_id_updated += 1; + self.subscriber + .on_connection_id_updated(&mut context.recorder, meta, event); + } + #[inline] + fn on_ecn_state_changed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::EcnStateChanged, + ) { + context.ecn_state_changed += 1; + self.subscriber + .on_ecn_state_changed(&mut context.recorder, meta, event); + } + #[inline] + fn on_connection_migration_denied( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionMigrationDenied, + ) { + context.connection_migration_denied += 1; + self.subscriber + .on_connection_migration_denied(&mut context.recorder, meta, event); + } + #[inline] + fn on_handshake_status_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::HandshakeStatusUpdated, + ) { + context.handshake_status_updated += 1; + self.subscriber + .on_handshake_status_updated(&mut context.recorder, meta, event); + } + #[inline] + fn on_tls_exporter_ready( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TlsExporterReady, + ) { + context.tls_exporter_ready += 1; + self.subscriber + .on_tls_exporter_ready(&mut context.recorder, meta, event); + } + #[inline] + fn on_path_challenge_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PathChallengeUpdated, + ) { + context.path_challenge_updated += 1; + self.subscriber + .on_path_challenge_updated(&mut context.recorder, meta, event); + } + #[inline] + fn on_tls_client_hello( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TlsClientHello, + ) { + context.tls_client_hello += 1; + self.subscriber + .on_tls_client_hello(&mut context.recorder, meta, event); + } + #[inline] + fn on_tls_server_hello( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TlsServerHello, + ) { + context.tls_server_hello += 1; + self.subscriber + .on_tls_server_hello(&mut context.recorder, meta, event); + } + #[inline] + fn on_rx_stream_progress( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::RxStreamProgress, + ) { + context.rx_stream_progress += 1; + self.subscriber + .on_rx_stream_progress(&mut context.recorder, meta, event); + } + #[inline] + fn on_tx_stream_progress( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TxStreamProgress, + ) { + context.tx_stream_progress += 1; + self.subscriber + .on_tx_stream_progress(&mut context.recorder, meta, event); + } + #[inline] + fn on_keep_alive_timer_expired( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::KeepAliveTimerExpired, + ) { + context.keep_alive_timer_expired += 1; + self.subscriber + .on_keep_alive_timer_expired(&mut context.recorder, meta, event); + } + #[inline] + fn on_mtu_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::MtuUpdated, + ) { + context.mtu_updated += 1; + self.subscriber + .on_mtu_updated(&mut context.recorder, meta, event); + } + #[inline] + fn on_slow_start_exited( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::SlowStartExited, + ) { + context.slow_start_exited += 1; + self.subscriber + .on_slow_start_exited(&mut context.recorder, meta, event); + } + #[inline] + fn on_delivery_rate_sampled( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DeliveryRateSampled, + ) { + context.delivery_rate_sampled += 1; + self.subscriber + .on_delivery_rate_sampled(&mut context.recorder, meta, event); + } + #[inline] + fn on_pacing_rate_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacingRateUpdated, + ) { + context.pacing_rate_updated += 1; + self.subscriber + .on_pacing_rate_updated(&mut context.recorder, meta, event); + } + #[inline] + fn on_bbr_state_changed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::BbrStateChanged, + ) { + context.bbr_state_changed += 1; + self.subscriber + .on_bbr_state_changed(&mut context.recorder, meta, event); + } + #[inline] + fn on_dc_state_changed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DcStateChanged, + ) { + context.dc_state_changed += 1; + self.subscriber + .on_dc_state_changed(&mut context.recorder, meta, event); + } +} +impl Drop for Context { + fn drop(&mut self) { + self.recorder.increment_counter( + "application_protocol_information", + self.application_protocol_information as _, + ); + self.recorder + .increment_counter("server_name_information", self.server_name_information as _); + self.recorder + .increment_counter("packet_skipped", self.packet_skipped as _); + self.recorder + .increment_counter("packet_sent", self.packet_sent as _); + self.recorder + .increment_counter("packet_received", self.packet_received as _); + self.recorder + .increment_counter("active_path_updated", self.active_path_updated as _); + self.recorder + .increment_counter("path_created", self.path_created as _); + self.recorder + .increment_counter("frame_sent", self.frame_sent as _); + self.recorder + .increment_counter("frame_received", self.frame_received as _); + self.recorder + .increment_counter("packet_lost", self.packet_lost as _); + self.recorder + .increment_counter("recovery_metrics", self.recovery_metrics as _); + self.recorder + .increment_counter("congestion", self.congestion as _); + self.recorder + .increment_counter("ack_processed", self.ack_processed as _); + self.recorder + .increment_counter("rx_ack_range_dropped", self.rx_ack_range_dropped as _); + self.recorder + .increment_counter("ack_range_received", self.ack_range_received as _); + self.recorder + .increment_counter("ack_range_sent", self.ack_range_sent as _); + self.recorder + .increment_counter("packet_dropped", self.packet_dropped as _); + self.recorder + .increment_counter("key_update", self.key_update as _); + self.recorder + .increment_counter("key_space_discarded", self.key_space_discarded as _); + self.recorder + .increment_counter("connection_started", self.connection_started as _); + self.recorder + .increment_counter("connection_closed", self.connection_closed as _); + self.recorder + .increment_counter("duplicate_packet", self.duplicate_packet as _); + self.recorder.increment_counter( + "transport_parameters_received", + self.transport_parameters_received as _, + ); + self.recorder + .increment_counter("datagram_sent", self.datagram_sent as _); + self.recorder + .increment_counter("datagram_received", self.datagram_received as _); + self.recorder + .increment_counter("datagram_dropped", self.datagram_dropped as _); + self.recorder + .increment_counter("connection_id_updated", self.connection_id_updated as _); + self.recorder + .increment_counter("ecn_state_changed", self.ecn_state_changed as _); + self.recorder.increment_counter( + "connection_migration_denied", + self.connection_migration_denied as _, + ); + self.recorder.increment_counter( + "handshake_status_updated", + self.handshake_status_updated as _, + ); + self.recorder + .increment_counter("tls_exporter_ready", self.tls_exporter_ready as _); + self.recorder + .increment_counter("path_challenge_updated", self.path_challenge_updated as _); + self.recorder + .increment_counter("tls_client_hello", self.tls_client_hello as _); + self.recorder + .increment_counter("tls_server_hello", self.tls_server_hello as _); + self.recorder + .increment_counter("rx_stream_progress", self.rx_stream_progress as _); + self.recorder + .increment_counter("tx_stream_progress", self.tx_stream_progress as _); + self.recorder.increment_counter( + "keep_alive_timer_expired", + self.keep_alive_timer_expired as _, + ); + self.recorder + .increment_counter("mtu_updated", self.mtu_updated as _); + self.recorder + .increment_counter("slow_start_exited", self.slow_start_exited as _); + self.recorder + .increment_counter("delivery_rate_sampled", self.delivery_rate_sampled as _); + self.recorder + .increment_counter("pacing_rate_updated", self.pacing_rate_updated as _); + self.recorder + .increment_counter("bbr_state_changed", self.bbr_state_changed as _); + self.recorder + .increment_counter("dc_state_changed", self.dc_state_changed as _); + } +} diff --git a/quic/s2n-quic-core/src/event/generated/metrics/aggregate.rs b/quic/s2n-quic-core/src/event/generated/metrics/aggregate.rs new file mode 100644 index 000000000..a05c5de9f --- /dev/null +++ b/quic/s2n-quic-core/src/event/generated/metrics/aggregate.rs @@ -0,0 +1,1213 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// DO NOT MODIFY THIS FILE +// This file was generated with the `s2n-quic-events` crate and any required +// changes should be made there. + +use crate::event::{ + self, api, + metrics::aggregate::{info, Info, Recorder, Registry}, +}; +use alloc::{boxed::Box, vec::Vec}; +const fn new_str(bytes: &'static str) -> info::Str<'static> { + unsafe { info::Str::new_unchecked(bytes) } +} +static INFO: &[Info; 57usize] = &[ + info::Builder { + id: 0usize, + name: new_str("application_protocol_information\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 1usize, + name: new_str("server_name_information\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 2usize, + name: new_str("packet_skipped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 3usize, + name: new_str("packet_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 4usize, + name: new_str("packet_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 5usize, + name: new_str("active_path_updated\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 6usize, + name: new_str("path_created\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 7usize, + name: new_str("frame_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 8usize, + name: new_str("frame_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 9usize, + name: new_str("packet_lost\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 10usize, + name: new_str("recovery_metrics\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 11usize, + name: new_str("congestion\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 12usize, + name: new_str("rx_ack_range_dropped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 13usize, + name: new_str("ack_range_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 14usize, + name: new_str("ack_range_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 15usize, + name: new_str("packet_dropped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 16usize, + name: new_str("key_update\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 17usize, + name: new_str("key_space_discarded\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 18usize, + name: new_str("connection_started\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 19usize, + name: new_str("connection_closed\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 20usize, + name: new_str("duplicate_packet\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 21usize, + name: new_str("transport_parameters_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 22usize, + name: new_str("datagram_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 23usize, + name: new_str("datagram_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 24usize, + name: new_str("datagram_dropped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 25usize, + name: new_str("connection_id_updated\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 26usize, + name: new_str("ecn_state_changed\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 27usize, + name: new_str("connection_migration_denied\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 28usize, + name: new_str("handshake_status_updated\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 29usize, + name: new_str("tls_exporter_ready\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 30usize, + name: new_str("path_challenge_updated\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 31usize, + name: new_str("tls_client_hello\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 32usize, + name: new_str("tls_server_hello\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 33usize, + name: new_str("rx_stream_progress\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 34usize, + name: new_str("tx_stream_progress\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 35usize, + name: new_str("keep_alive_timer_expired\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 36usize, + name: new_str("mtu_updated\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 37usize, + name: new_str("slow_start_exited\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 38usize, + name: new_str("delivery_rate_sampled\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 39usize, + name: new_str("pacing_rate_updated\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 40usize, + name: new_str("bbr_state_changed\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 41usize, + name: new_str("dc_state_changed\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 42usize, + name: new_str("version_information\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 43usize, + name: new_str("endpoint_packet_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 44usize, + name: new_str("endpoint_packet_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 45usize, + name: new_str("endpoint_datagram_sent\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 46usize, + name: new_str("endpoint_datagram_received\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 47usize, + name: new_str("endpoint_datagram_dropped\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 48usize, + name: new_str("endpoint_connection_attempt_failed\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 49usize, + name: new_str("platform_tx\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 50usize, + name: new_str("platform_tx_error\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 51usize, + name: new_str("platform_rx\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 52usize, + name: new_str("platform_rx_error\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 53usize, + name: new_str("platform_feature_configured\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 54usize, + name: new_str("platform_event_loop_wakeup\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 55usize, + name: new_str("platform_event_loop_sleep\0"), + units: new_str("\0"), + } + .build(), + info::Builder { + id: 56usize, + name: new_str("platform_event_loop_started\0"), + units: new_str("\0"), + } + .build(), +]; +pub struct Subscriber { + #[allow(dead_code)] + counters: Box<[R::Counter]>, + #[allow(dead_code)] + measures: Box<[R::Measure]>, + #[allow(dead_code)] + gauges: Box<[R::Gauge]>, + #[allow(dead_code)] + timers: Box<[R::Timer]>, + #[allow(dead_code)] + registry: R, +} +impl Default for Subscriber { + fn default() -> Self { + Self::new(R::default()) + } +} +impl Subscriber { + #[doc = r" Creates a new subscriber with the given registry"] + #[doc = r""] + #[doc = r" # Note"] + #[doc = r""] + #[doc = r" All of the recorders are registered on initialization and cached for the lifetime"] + #[doc = r" of the subscriber."] + #[allow(unused_mut)] + #[inline] + pub fn new(registry: R) -> Self { + let mut counters = Vec::with_capacity(57usize); + let mut measures = Vec::with_capacity(0usize); + let mut gauges = Vec::with_capacity(0usize); + let mut timers = Vec::with_capacity(0usize); + counters.push(registry.register_counter(&INFO[0usize])); + counters.push(registry.register_counter(&INFO[1usize])); + counters.push(registry.register_counter(&INFO[2usize])); + counters.push(registry.register_counter(&INFO[3usize])); + counters.push(registry.register_counter(&INFO[4usize])); + counters.push(registry.register_counter(&INFO[5usize])); + counters.push(registry.register_counter(&INFO[6usize])); + counters.push(registry.register_counter(&INFO[7usize])); + counters.push(registry.register_counter(&INFO[8usize])); + counters.push(registry.register_counter(&INFO[9usize])); + counters.push(registry.register_counter(&INFO[10usize])); + counters.push(registry.register_counter(&INFO[11usize])); + counters.push(registry.register_counter(&INFO[12usize])); + counters.push(registry.register_counter(&INFO[13usize])); + counters.push(registry.register_counter(&INFO[14usize])); + counters.push(registry.register_counter(&INFO[15usize])); + counters.push(registry.register_counter(&INFO[16usize])); + counters.push(registry.register_counter(&INFO[17usize])); + counters.push(registry.register_counter(&INFO[18usize])); + counters.push(registry.register_counter(&INFO[19usize])); + counters.push(registry.register_counter(&INFO[20usize])); + counters.push(registry.register_counter(&INFO[21usize])); + counters.push(registry.register_counter(&INFO[22usize])); + counters.push(registry.register_counter(&INFO[23usize])); + counters.push(registry.register_counter(&INFO[24usize])); + counters.push(registry.register_counter(&INFO[25usize])); + counters.push(registry.register_counter(&INFO[26usize])); + counters.push(registry.register_counter(&INFO[27usize])); + counters.push(registry.register_counter(&INFO[28usize])); + counters.push(registry.register_counter(&INFO[29usize])); + counters.push(registry.register_counter(&INFO[30usize])); + counters.push(registry.register_counter(&INFO[31usize])); + counters.push(registry.register_counter(&INFO[32usize])); + counters.push(registry.register_counter(&INFO[33usize])); + counters.push(registry.register_counter(&INFO[34usize])); + counters.push(registry.register_counter(&INFO[35usize])); + counters.push(registry.register_counter(&INFO[36usize])); + counters.push(registry.register_counter(&INFO[37usize])); + counters.push(registry.register_counter(&INFO[38usize])); + counters.push(registry.register_counter(&INFO[39usize])); + counters.push(registry.register_counter(&INFO[40usize])); + counters.push(registry.register_counter(&INFO[41usize])); + counters.push(registry.register_counter(&INFO[42usize])); + counters.push(registry.register_counter(&INFO[43usize])); + counters.push(registry.register_counter(&INFO[44usize])); + counters.push(registry.register_counter(&INFO[45usize])); + counters.push(registry.register_counter(&INFO[46usize])); + counters.push(registry.register_counter(&INFO[47usize])); + counters.push(registry.register_counter(&INFO[48usize])); + counters.push(registry.register_counter(&INFO[49usize])); + counters.push(registry.register_counter(&INFO[50usize])); + counters.push(registry.register_counter(&INFO[51usize])); + counters.push(registry.register_counter(&INFO[52usize])); + counters.push(registry.register_counter(&INFO[53usize])); + counters.push(registry.register_counter(&INFO[54usize])); + counters.push(registry.register_counter(&INFO[55usize])); + counters.push(registry.register_counter(&INFO[56usize])); + Self { + counters: counters.into(), + measures: measures.into(), + gauges: gauges.into(), + timers: timers.into(), + registry, + } + } + #[doc = r" Returns all of the registered counters"] + #[inline] + pub fn counters(&self) -> impl Iterator + '_ { + self.counters + .iter() + .enumerate() + .map(|(idx, entry)| match idx { + 0usize => (&INFO[0usize], entry), + 1usize => (&INFO[1usize], entry), + 2usize => (&INFO[2usize], entry), + 3usize => (&INFO[3usize], entry), + 4usize => (&INFO[4usize], entry), + 5usize => (&INFO[5usize], entry), + 6usize => (&INFO[6usize], entry), + 7usize => (&INFO[7usize], entry), + 8usize => (&INFO[8usize], entry), + 9usize => (&INFO[9usize], entry), + 10usize => (&INFO[10usize], entry), + 11usize => (&INFO[11usize], entry), + 12usize => (&INFO[12usize], entry), + 13usize => (&INFO[13usize], entry), + 14usize => (&INFO[14usize], entry), + 15usize => (&INFO[15usize], entry), + 16usize => (&INFO[16usize], entry), + 17usize => (&INFO[17usize], entry), + 18usize => (&INFO[18usize], entry), + 19usize => (&INFO[19usize], entry), + 20usize => (&INFO[20usize], entry), + 21usize => (&INFO[21usize], entry), + 22usize => (&INFO[22usize], entry), + 23usize => (&INFO[23usize], entry), + 24usize => (&INFO[24usize], entry), + 25usize => (&INFO[25usize], entry), + 26usize => (&INFO[26usize], entry), + 27usize => (&INFO[27usize], entry), + 28usize => (&INFO[28usize], entry), + 29usize => (&INFO[29usize], entry), + 30usize => (&INFO[30usize], entry), + 31usize => (&INFO[31usize], entry), + 32usize => (&INFO[32usize], entry), + 33usize => (&INFO[33usize], entry), + 34usize => (&INFO[34usize], entry), + 35usize => (&INFO[35usize], entry), + 36usize => (&INFO[36usize], entry), + 37usize => (&INFO[37usize], entry), + 38usize => (&INFO[38usize], entry), + 39usize => (&INFO[39usize], entry), + 40usize => (&INFO[40usize], entry), + 41usize => (&INFO[41usize], entry), + 42usize => (&INFO[42usize], entry), + 43usize => (&INFO[43usize], entry), + 44usize => (&INFO[44usize], entry), + 45usize => (&INFO[45usize], entry), + 46usize => (&INFO[46usize], entry), + 47usize => (&INFO[47usize], entry), + 48usize => (&INFO[48usize], entry), + 49usize => (&INFO[49usize], entry), + 50usize => (&INFO[50usize], entry), + 51usize => (&INFO[51usize], entry), + 52usize => (&INFO[52usize], entry), + 53usize => (&INFO[53usize], entry), + 54usize => (&INFO[54usize], entry), + 55usize => (&INFO[55usize], entry), + 56usize => (&INFO[56usize], entry), + _ => unsafe { core::hint::unreachable_unchecked() }, + }) + } + #[allow(dead_code)] + #[inline(always)] + fn count(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let counter = unsafe { self.counters.get_unchecked(id) }; + counter.record(info, value); + } + #[doc = r" Returns all of the registered measures"] + #[inline] + pub fn measures(&self) -> impl Iterator + '_ { + core::iter::empty() + } + #[allow(dead_code)] + #[inline(always)] + fn measure(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let measure = unsafe { self.measures.get_unchecked(id) }; + measure.record(info, value); + } + #[doc = r" Returns all of the registered gauges"] + #[inline] + pub fn gauges(&self) -> impl Iterator + '_ { + core::iter::empty() + } + #[allow(dead_code)] + #[inline(always)] + fn gauge(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let gauge = unsafe { self.gauges.get_unchecked(id) }; + gauge.record(info, value); + } + #[doc = r" Returns all of the registered timers"] + #[inline] + pub fn timers(&self) -> impl Iterator + '_ { + core::iter::empty() + } + #[allow(dead_code)] + #[inline(always)] + fn time(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let timer = unsafe { self.timers.get_unchecked(id) }; + timer.record(info, value); + } +} +impl event::Subscriber for Subscriber { + type ConnectionContext = (); + fn create_connection_context( + &mut self, + _meta: &api::ConnectionMeta, + _info: &api::ConnectionInfo, + ) -> Self::ConnectionContext { + } + #[inline] + fn on_application_protocol_information( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationProtocolInformation, + ) { + self.count(0usize, 0usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_server_name_information( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ServerNameInformation, + ) { + self.count(1usize, 1usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_packet_skipped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketSkipped, + ) { + self.count(2usize, 2usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_packet_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketSent, + ) { + self.count(3usize, 3usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_packet_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketReceived, + ) { + self.count(4usize, 4usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_active_path_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ActivePathUpdated, + ) { + self.count(5usize, 5usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_path_created( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PathCreated, + ) { + self.count(6usize, 6usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_frame_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::FrameSent, + ) { + self.count(7usize, 7usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_frame_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::FrameReceived, + ) { + self.count(8usize, 8usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_packet_lost( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketLost, + ) { + self.count(9usize, 9usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_recovery_metrics( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::RecoveryMetrics, + ) { + self.count(10usize, 10usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_congestion( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::Congestion, + ) { + self.count(11usize, 11usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_rx_ack_range_dropped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::RxAckRangeDropped, + ) { + self.count(12usize, 12usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_ack_range_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::AckRangeReceived, + ) { + self.count(13usize, 13usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_ack_range_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::AckRangeSent, + ) { + self.count(14usize, 14usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_packet_dropped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacketDropped, + ) { + self.count(15usize, 15usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_key_update( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::KeyUpdate, + ) { + self.count(16usize, 16usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_key_space_discarded( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::KeySpaceDiscarded, + ) { + self.count(17usize, 17usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_connection_started( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionStarted, + ) { + self.count(18usize, 18usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_connection_closed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionClosed, + ) { + self.count(19usize, 19usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_duplicate_packet( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DuplicatePacket, + ) { + self.count(20usize, 20usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_transport_parameters_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TransportParametersReceived, + ) { + self.count(21usize, 21usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_datagram_sent( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DatagramSent, + ) { + self.count(22usize, 22usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_datagram_received( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DatagramReceived, + ) { + self.count(23usize, 23usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_datagram_dropped( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DatagramDropped, + ) { + self.count(24usize, 24usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_connection_id_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionIdUpdated, + ) { + self.count(25usize, 25usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_ecn_state_changed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::EcnStateChanged, + ) { + self.count(26usize, 26usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_connection_migration_denied( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ConnectionMigrationDenied, + ) { + self.count(27usize, 27usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_handshake_status_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::HandshakeStatusUpdated, + ) { + self.count(28usize, 28usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_tls_exporter_ready( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TlsExporterReady, + ) { + self.count(29usize, 29usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_path_challenge_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PathChallengeUpdated, + ) { + self.count(30usize, 30usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_tls_client_hello( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TlsClientHello, + ) { + self.count(31usize, 31usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_tls_server_hello( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TlsServerHello, + ) { + self.count(32usize, 32usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_rx_stream_progress( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::RxStreamProgress, + ) { + self.count(33usize, 33usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_tx_stream_progress( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::TxStreamProgress, + ) { + self.count(34usize, 34usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_keep_alive_timer_expired( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::KeepAliveTimerExpired, + ) { + self.count(35usize, 35usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_mtu_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::MtuUpdated, + ) { + self.count(36usize, 36usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_slow_start_exited( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::SlowStartExited, + ) { + self.count(37usize, 37usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_delivery_rate_sampled( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DeliveryRateSampled, + ) { + self.count(38usize, 38usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_pacing_rate_updated( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::PacingRateUpdated, + ) { + self.count(39usize, 39usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_bbr_state_changed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::BbrStateChanged, + ) { + self.count(40usize, 40usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_dc_state_changed( + &mut self, + context: &mut Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::DcStateChanged, + ) { + self.count(41usize, 41usize, 1); + let _ = context; + let _ = meta; + let _ = event; + } + #[inline] + fn on_version_information( + &mut self, + meta: &api::EndpointMeta, + event: &api::VersionInformation, + ) { + self.count(42usize, 42usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_endpoint_packet_sent( + &mut self, + meta: &api::EndpointMeta, + event: &api::EndpointPacketSent, + ) { + self.count(43usize, 43usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_endpoint_packet_received( + &mut self, + meta: &api::EndpointMeta, + event: &api::EndpointPacketReceived, + ) { + self.count(44usize, 44usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_endpoint_datagram_sent( + &mut self, + meta: &api::EndpointMeta, + event: &api::EndpointDatagramSent, + ) { + self.count(45usize, 45usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_endpoint_datagram_received( + &mut self, + meta: &api::EndpointMeta, + event: &api::EndpointDatagramReceived, + ) { + self.count(46usize, 46usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_endpoint_datagram_dropped( + &mut self, + meta: &api::EndpointMeta, + event: &api::EndpointDatagramDropped, + ) { + self.count(47usize, 47usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_endpoint_connection_attempt_failed( + &mut self, + meta: &api::EndpointMeta, + event: &api::EndpointConnectionAttemptFailed, + ) { + self.count(48usize, 48usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_tx(&mut self, meta: &api::EndpointMeta, event: &api::PlatformTx) { + self.count(49usize, 49usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_tx_error(&mut self, meta: &api::EndpointMeta, event: &api::PlatformTxError) { + self.count(50usize, 50usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_rx(&mut self, meta: &api::EndpointMeta, event: &api::PlatformRx) { + self.count(51usize, 51usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_rx_error(&mut self, meta: &api::EndpointMeta, event: &api::PlatformRxError) { + self.count(52usize, 52usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_feature_configured( + &mut self, + meta: &api::EndpointMeta, + event: &api::PlatformFeatureConfigured, + ) { + self.count(53usize, 53usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_event_loop_wakeup( + &mut self, + meta: &api::EndpointMeta, + event: &api::PlatformEventLoopWakeup, + ) { + self.count(54usize, 54usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_event_loop_sleep( + &mut self, + meta: &api::EndpointMeta, + event: &api::PlatformEventLoopSleep, + ) { + self.count(55usize, 55usize, 1); + let _ = event; + let _ = meta; + } + #[inline] + fn on_platform_event_loop_started( + &mut self, + meta: &api::EndpointMeta, + event: &api::PlatformEventLoopStarted, + ) { + self.count(56usize, 56usize, 1); + let _ = event; + let _ = meta; + } +} diff --git a/quic/s2n-quic-core/src/event/generated/metrics/probe.rs b/quic/s2n-quic-core/src/event/generated/metrics/probe.rs new file mode 100644 index 000000000..0a85f7e9c --- /dev/null +++ b/quic/s2n-quic-core/src/event/generated/metrics/probe.rs @@ -0,0 +1,268 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// DO NOT MODIFY THIS FILE +// This file was generated with the `s2n-quic-events` crate and any required +// changes should be made there. + +use crate::{ + event::metrics::aggregate::{self, Info, Recorder}, + probe::define, +}; +mod counter { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + match info.id { + 0usize => Self(application_protocol_information), + 1usize => Self(server_name_information), + 2usize => Self(packet_skipped), + 3usize => Self(packet_sent), + 4usize => Self(packet_received), + 5usize => Self(active_path_updated), + 6usize => Self(path_created), + 7usize => Self(frame_sent), + 8usize => Self(frame_received), + 9usize => Self(packet_lost), + 10usize => Self(recovery_metrics), + 11usize => Self(congestion), + 12usize => Self(rx_ack_range_dropped), + 13usize => Self(ack_range_received), + 14usize => Self(ack_range_sent), + 15usize => Self(packet_dropped), + 16usize => Self(key_update), + 17usize => Self(key_space_discarded), + 18usize => Self(connection_started), + 19usize => Self(connection_closed), + 20usize => Self(duplicate_packet), + 21usize => Self(transport_parameters_received), + 22usize => Self(datagram_sent), + 23usize => Self(datagram_received), + 24usize => Self(datagram_dropped), + 25usize => Self(connection_id_updated), + 26usize => Self(ecn_state_changed), + 27usize => Self(connection_migration_denied), + 28usize => Self(handshake_status_updated), + 29usize => Self(tls_exporter_ready), + 30usize => Self(path_challenge_updated), + 31usize => Self(tls_client_hello), + 32usize => Self(tls_server_hello), + 33usize => Self(rx_stream_progress), + 34usize => Self(tx_stream_progress), + 35usize => Self(keep_alive_timer_expired), + 36usize => Self(mtu_updated), + 37usize => Self(slow_start_exited), + 38usize => Self(delivery_rate_sampled), + 39usize => Self(pacing_rate_updated), + 40usize => Self(bbr_state_changed), + 41usize => Self(dc_state_changed), + 42usize => Self(version_information), + 43usize => Self(endpoint_packet_sent), + 44usize => Self(endpoint_packet_received), + 45usize => Self(endpoint_datagram_sent), + 46usize => Self(endpoint_datagram_received), + 47usize => Self(endpoint_datagram_dropped), + 48usize => Self(endpoint_connection_attempt_failed), + 49usize => Self(platform_tx), + 50usize => Self(platform_tx_error), + 51usize => Self(platform_rx), + 52usize => Self(platform_rx_error), + 53usize => Self(platform_feature_configured), + 54usize => Self(platform_event_loop_wakeup), + 55usize => Self(platform_event_loop_sleep), + 56usize => Self(platform_event_loop_started), + _ => unreachable!("invalid info: {info:?}"), + } + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } + super::define!( + extern "probe" { + # [link_name = s2n_quic__event__counter__application_protocol_information] + fn application_protocol_information(value: u64); + # [link_name = s2n_quic__event__counter__server_name_information] + fn server_name_information(value: u64); + # [link_name = s2n_quic__event__counter__packet_skipped] + fn packet_skipped(value: u64); + # [link_name = s2n_quic__event__counter__packet_sent] + fn packet_sent(value: u64); + # [link_name = s2n_quic__event__counter__packet_received] + fn packet_received(value: u64); + # [link_name = s2n_quic__event__counter__active_path_updated] + fn active_path_updated(value: u64); + # [link_name = s2n_quic__event__counter__path_created] + fn path_created(value: u64); + # [link_name = s2n_quic__event__counter__frame_sent] + fn frame_sent(value: u64); + # [link_name = s2n_quic__event__counter__frame_received] + fn frame_received(value: u64); + # [link_name = s2n_quic__event__counter__packet_lost] + fn packet_lost(value: u64); + # [link_name = s2n_quic__event__counter__recovery_metrics] + fn recovery_metrics(value: u64); + # [link_name = s2n_quic__event__counter__congestion] + fn congestion(value: u64); + # [link_name = s2n_quic__event__counter__rx_ack_range_dropped] + fn rx_ack_range_dropped(value: u64); + # [link_name = s2n_quic__event__counter__ack_range_received] + fn ack_range_received(value: u64); + # [link_name = s2n_quic__event__counter__ack_range_sent] + fn ack_range_sent(value: u64); + # [link_name = s2n_quic__event__counter__packet_dropped] + fn packet_dropped(value: u64); + # [link_name = s2n_quic__event__counter__key_update] + fn key_update(value: u64); + # [link_name = s2n_quic__event__counter__key_space_discarded] + fn key_space_discarded(value: u64); + # [link_name = s2n_quic__event__counter__connection_started] + fn connection_started(value: u64); + # [link_name = s2n_quic__event__counter__connection_closed] + fn connection_closed(value: u64); + # [link_name = s2n_quic__event__counter__duplicate_packet] + fn duplicate_packet(value: u64); + # [link_name = s2n_quic__event__counter__transport_parameters_received] + fn transport_parameters_received(value: u64); + # [link_name = s2n_quic__event__counter__datagram_sent] + fn datagram_sent(value: u64); + # [link_name = s2n_quic__event__counter__datagram_received] + fn datagram_received(value: u64); + # [link_name = s2n_quic__event__counter__datagram_dropped] + fn datagram_dropped(value: u64); + # [link_name = s2n_quic__event__counter__connection_id_updated] + fn connection_id_updated(value: u64); + # [link_name = s2n_quic__event__counter__ecn_state_changed] + fn ecn_state_changed(value: u64); + # [link_name = s2n_quic__event__counter__connection_migration_denied] + fn connection_migration_denied(value: u64); + # [link_name = s2n_quic__event__counter__handshake_status_updated] + fn handshake_status_updated(value: u64); + # [link_name = s2n_quic__event__counter__tls_exporter_ready] + fn tls_exporter_ready(value: u64); + # [link_name = s2n_quic__event__counter__path_challenge_updated] + fn path_challenge_updated(value: u64); + # [link_name = s2n_quic__event__counter__tls_client_hello] + fn tls_client_hello(value: u64); + # [link_name = s2n_quic__event__counter__tls_server_hello] + fn tls_server_hello(value: u64); + # [link_name = s2n_quic__event__counter__rx_stream_progress] + fn rx_stream_progress(value: u64); + # [link_name = s2n_quic__event__counter__tx_stream_progress] + fn tx_stream_progress(value: u64); + # [link_name = s2n_quic__event__counter__keep_alive_timer_expired] + fn keep_alive_timer_expired(value: u64); + # [link_name = s2n_quic__event__counter__mtu_updated] + fn mtu_updated(value: u64); + # [link_name = s2n_quic__event__counter__slow_start_exited] + fn slow_start_exited(value: u64); + # [link_name = s2n_quic__event__counter__delivery_rate_sampled] + fn delivery_rate_sampled(value: u64); + # [link_name = s2n_quic__event__counter__pacing_rate_updated] + fn pacing_rate_updated(value: u64); + # [link_name = s2n_quic__event__counter__bbr_state_changed] + fn bbr_state_changed(value: u64); + # [link_name = s2n_quic__event__counter__dc_state_changed] + fn dc_state_changed(value: u64); + # [link_name = s2n_quic__event__counter__version_information] + fn version_information(value: u64); + # [link_name = s2n_quic__event__counter__endpoint_packet_sent] + fn endpoint_packet_sent(value: u64); + # [link_name = s2n_quic__event__counter__endpoint_packet_received] + fn endpoint_packet_received(value: u64); + # [link_name = s2n_quic__event__counter__endpoint_datagram_sent] + fn endpoint_datagram_sent(value: u64); + # [link_name = s2n_quic__event__counter__endpoint_datagram_received] + fn endpoint_datagram_received(value: u64); + # [link_name = s2n_quic__event__counter__endpoint_datagram_dropped] + fn endpoint_datagram_dropped(value: u64); + # [link_name = s2n_quic__event__counter__endpoint_connection_attempt_failed] + fn endpoint_connection_attempt_failed(value: u64); + # [link_name = s2n_quic__event__counter__platform_tx] + fn platform_tx(value: u64); + # [link_name = s2n_quic__event__counter__platform_tx_error] + fn platform_tx_error(value: u64); + # [link_name = s2n_quic__event__counter__platform_rx] + fn platform_rx(value: u64); + # [link_name = s2n_quic__event__counter__platform_rx_error] + fn platform_rx_error(value: u64); + # [link_name = s2n_quic__event__counter__platform_feature_configured] + fn platform_feature_configured(value: u64); + # [link_name = s2n_quic__event__counter__platform_event_loop_wakeup] + fn platform_event_loop_wakeup(value: u64); + # [link_name = s2n_quic__event__counter__platform_event_loop_sleep] + fn platform_event_loop_sleep(value: u64); + # [link_name = s2n_quic__event__counter__platform_event_loop_started] + fn platform_event_loop_started(value: u64); + } + ); +} +mod measure { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + unreachable!("invalid info: {info:?}") + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } +} +mod gauge { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + unreachable!("invalid info: {info:?}") + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } +} +mod timer { + use super::Info; + pub struct Recorder(fn(u64)); + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + unreachable!("invalid info: {info:?}") + } + } + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } +} +#[derive(Default)] +pub struct Registry(()); +impl aggregate::Registry for Registry { + type Counter = counter::Recorder; + type Measure = measure::Recorder; + type Gauge = gauge::Recorder; + type Timer = timer::Recorder; + #[inline] + fn register_counter(&self, info: &'static Info) -> Self::Counter { + counter::Recorder::new(info) + } + #[inline] + fn register_measure(&self, info: &'static Info) -> Self::Measure { + measure::Recorder::new(info) + } + #[inline] + fn register_gauge(&self, info: &'static Info) -> Self::Gauge { + gauge::Recorder::new(info) + } + #[inline] + fn register_timer(&self, info: &'static Info) -> Self::Timer { + timer::Recorder::new(info) + } +} diff --git a/quic/s2n-quic-core/src/event/metrics.rs b/quic/s2n-quic-core/src/event/metrics.rs index 92547d0c4..2830377cc 100644 --- a/quic/s2n-quic-core/src/event/metrics.rs +++ b/quic/s2n-quic-core/src/event/metrics.rs @@ -1,7 +1,9 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -pub use super::generated::*; +pub use super::generated::metrics::*; + +pub mod aggregate; /// A Recorder should arrange to emit the properties and counters on Drop into some output. pub trait Recorder: 'static + Send + Sync { diff --git a/quic/s2n-quic-core/src/event/metrics/aggregate.rs b/quic/s2n-quic-core/src/event/metrics/aggregate.rs new file mode 100644 index 000000000..33dcadb26 --- /dev/null +++ b/quic/s2n-quic-core/src/event/metrics/aggregate.rs @@ -0,0 +1,210 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(feature = "alloc")] +pub use crate::event::generated::metrics::aggregate::*; + +pub mod probe; + +pub trait Registry: 'static + Send + Sync { + type Counter: Recorder; + type Measure: Recorder; + type Gauge: Recorder; + type Timer: Recorder; + + fn register_counter(&self, info: &'static Info) -> Self::Counter; + + fn register_measure(&self, info: &'static Info) -> Self::Measure; + + fn register_gauge(&self, info: &'static Info) -> Self::Gauge; + + fn register_timer(&self, info: &'static Info) -> Self::Timer; +} + +impl Registry for (A, B) +where + A: Registry, + B: Registry, +{ + type Counter = (A::Counter, B::Counter); + type Measure = (A::Measure, B::Measure); + type Gauge = (A::Gauge, B::Gauge); + type Timer = (A::Timer, B::Timer); + + #[inline] + fn register_counter(&self, info: &'static Info) -> Self::Counter { + (self.0.register_counter(info), self.1.register_counter(info)) + } + + #[inline] + fn register_measure(&self, info: &'static Info) -> Self::Measure { + (self.0.register_measure(info), self.1.register_measure(info)) + } + + #[inline] + fn register_gauge(&self, info: &'static Info) -> Self::Gauge { + (self.0.register_gauge(info), self.1.register_gauge(info)) + } + + #[inline] + fn register_timer(&self, info: &'static Info) -> Self::Timer { + (self.0.register_timer(info), self.1.register_timer(info)) + } +} + +#[cfg(feature = "alloc")] +impl Registry for alloc::sync::Arc { + type Counter = T::Counter; + type Measure = T::Measure; + type Gauge = T::Gauge; + type Timer = T::Timer; + + #[inline] + fn register_counter(&self, info: &'static Info) -> Self::Counter { + self.as_ref().register_counter(info) + } + + #[inline] + fn register_measure(&self, info: &'static Info) -> Self::Measure { + self.as_ref().register_measure(info) + } + + #[inline] + fn register_gauge(&self, info: &'static Info) -> Self::Gauge { + self.as_ref().register_gauge(info) + } + + #[inline] + fn register_timer(&self, info: &'static Info) -> Self::Timer { + self.as_ref().register_timer(info) + } +} + +pub trait Recorder: 'static + Send + Sync { + fn record(&self, info: &'static Info, value: u64); +} + +impl Recorder for (A, B) +where + A: Recorder, + B: Recorder, +{ + #[inline] + fn record(&self, info: &'static Info, value: u64) { + self.0.record(info, value); + self.1.record(info, value); + } +} + +#[cfg(target_has_atomic = "64")] +impl Recorder for core::sync::atomic::AtomicU64 { + #[inline] + fn record(&self, _info: &'static Info, value: u64) { + self.fetch_add(value, core::sync::atomic::Ordering::Relaxed); + } +} + +#[cfg(feature = "alloc")] +impl Recorder for alloc::sync::Arc { + #[inline] + fn record(&self, info: &'static Info, value: u64) { + self.as_ref().record(info, value); + } +} + +#[derive(Debug)] +#[non_exhaustive] +pub struct Info { + pub id: usize, + pub name: info::Str<'static>, + pub units: info::Str<'static>, +} + +pub mod info { + use super::Info; + use crate::probe; + use core::{ffi::CStr, fmt, ops}; + + #[doc(hidden)] + pub struct Builder { + pub id: usize, + pub name: Str<'static>, + pub units: Str<'static>, + } + + impl Builder { + #[inline] + pub const fn build(self) -> Info { + Info { + id: self.id, + name: self.name, + units: self.units, + } + } + } + + /// A str that is also a [`CStr`] + #[derive(Clone, Copy)] + pub struct Str<'a>(usize, &'a CStr); + + impl<'a> Str<'a> { + /// # Safety + /// + /// The provided value must end in a `\0` character + pub const unsafe fn new_unchecked(value: &'a str) -> Self { + unsafe { + Self( + value.len() - 1, + CStr::from_bytes_with_nul_unchecked(value.as_bytes()), + ) + } + } + } + + impl fmt::Debug for Str<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } + } + + impl fmt::Display for Str<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } + } + + impl ops::Deref for Str<'_> { + type Target = str; + + #[inline] + fn deref(&self) -> &Self::Target { + let len = self.0; + let ptr = self.1.as_ptr(); + unsafe { + let bytes = core::slice::from_raw_parts(ptr as *const u8, len); + core::str::from_utf8_unchecked(bytes) + } + } + } + + impl AsRef for Str<'_> { + #[inline] + fn as_ref(&self) -> &str { + self + } + } + + impl AsRef for Str<'_> { + #[inline] + fn as_ref(&self) -> &CStr { + self.1 + } + } + + impl probe::Arg for Str<'_> { + #[inline] + fn into_usdt(self) -> isize { + self.1.as_ptr() as _ + } + } +} diff --git a/quic/s2n-quic-core/src/event/metrics/aggregate/probe.rs b/quic/s2n-quic-core/src/event/metrics/aggregate/probe.rs new file mode 100644 index 000000000..d81a03f86 --- /dev/null +++ b/quic/s2n-quic-core/src/event/metrics/aggregate/probe.rs @@ -0,0 +1,5 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +pub mod dynamic; +pub use crate::event::generated::metrics::probe::*; diff --git a/quic/s2n-quic-core/src/event/metrics/aggregate/probe/dynamic.rs b/quic/s2n-quic-core/src/event/metrics/aggregate/probe/dynamic.rs new file mode 100644 index 000000000..8d85126dd --- /dev/null +++ b/quic/s2n-quic-core/src/event/metrics/aggregate/probe/dynamic.rs @@ -0,0 +1,91 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use crate::event::metrics::aggregate::{self, info::Str, Info}; + +#[derive(Clone, Debug, Default)] +pub struct Registry(()); + +impl aggregate::Registry for Registry { + type Counter = Counter; + type Measure = Measure; + type Gauge = Gauge; + type Timer = Measure; + + #[inline] + fn register_counter(&self, info: &'static Info) -> Self::Counter { + Self::Counter::new(info) + } + + #[inline] + fn register_measure(&self, info: &'static Info) -> Self::Measure { + Self::Measure::new(info) + } + + #[inline] + fn register_gauge(&self, info: &'static Info) -> Self::Gauge { + Self::Gauge::new(info) + } + + #[inline] + fn register_timer(&self, info: &'static Info) -> Self::Timer { + Self::Timer::new(info) + } +} + +macro_rules! recorder { + ($name:ident, $module:ident, $register:ident, $record:ident) => { + mod $module { + use super::*; + use crate::probe::define; + + define!( + extern "probe" { + #[link_name = $register] + fn register(id: usize, name: Str, units: Str); + + #[link_name = $record] + fn record(id: usize, value: u64); + } + ); + + #[derive(Copy, Clone, Debug, Default)] + pub struct $name(()); + + impl $name { + pub(super) fn new(info: &'static Info) -> Self { + register(info.id, info.name, info.units); + Self(()) + } + } + + impl aggregate::Recorder for $name { + #[inline] + fn record(&self, info: &'static Info, value: u64) { + record(info.id, value); + } + } + } + + pub use $module::$name; + }; +} + +recorder!( + Counter, + counter, + s2n_quic__counter__register, + s2n_quic__counter__record +); +recorder!( + Measure, + measure, + s2n_quic__measure__register, + s2n_quic__measure__record +); +recorder!( + Gauge, + gauge, + s2n_quic__gauge__register, + s2n_quic__gauge__record +); diff --git a/quic/s2n-quic-core/src/probe.rs b/quic/s2n-quic-core/src/probe.rs index c5d20eea2..3ebccebfa 100644 --- a/quic/s2n-quic-core/src/probe.rs +++ b/quic/s2n-quic-core/src/probe.rs @@ -67,16 +67,13 @@ pub use probe::probe as __usdt_emit__; macro_rules! __usdt_impl__ { ($provider:ident, $name:ident $(, $arg:ident)* $(,)?) => {{ // define a function with inline(never) to consolidate probes to this single location - let probe = { - #[inline(never)] - || { - $( - let $arg = $crate::probe::Arg::into_usdt($arg); - )* - $crate::probe::__usdt_emit__!($provider, $name, $($arg),*); - } - }; - probe(); + #[inline(never)] + fn probe($($arg: isize),*) { + $crate::probe::__usdt_emit__!($provider, $name, $($arg),*); + } + probe($( + $crate::probe::Arg::into_usdt($arg), + )*); }} } @@ -153,6 +150,13 @@ impl Arg for crate::varint::VarInt { } } +impl Arg for &core::ffi::CStr { + #[inline] + fn into_usdt(self) -> isize { + self.as_ptr() as _ + } +} + #[cfg(test)] mod tests { crate::probe::define!( diff --git a/quic/s2n-quic-events/src/main.rs b/quic/s2n-quic-events/src/main.rs index d5e73dbe0..703a2086b 100644 --- a/quic/s2n-quic-events/src/main.rs +++ b/quic/s2n-quic-events/src/main.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::quote; type Error = Box; type Result = core::result::Result; @@ -17,12 +17,14 @@ use output_mode::OutputMode; struct EventInfo<'a> { input_path: &'a str, output_path: &'a str, + crate_name: &'a str, output_mode: OutputMode, s2n_quic_core_path: TokenStream, api: TokenStream, builder: TokenStream, tracing_subscriber_attr: TokenStream, tracing_subscriber_def: TokenStream, + feature_alloc: TokenStream, } impl EventInfo<'_> { @@ -59,14 +61,12 @@ impl EventInfo<'_> { ); EventInfo { + crate_name: "s2n_quic", input_path: concat!( env!("CARGO_MANIFEST_DIR"), "/../s2n-quic-core/events/**/*.rs" ), - output_path: concat!( - env!("CARGO_MANIFEST_DIR"), - "/../s2n-quic-core/src/event/generated.rs" - ), + output_path: concat!(env!("CARGO_MANIFEST_DIR"), "/../s2n-quic-core/src/event"), output_mode: OutputMode::Mut, s2n_quic_core_path: quote!(crate), api: quote!(), @@ -75,6 +75,7 @@ impl EventInfo<'_> { #[cfg(feature = "event-tracing")] }, tracing_subscriber_def, + feature_alloc: quote!(#[cfg(feature = "alloc")]), } } @@ -104,13 +105,14 @@ impl EventInfo<'_> { ); EventInfo { + crate_name: "s2n_quic_dc", input_path: concat!( env!("CARGO_MANIFEST_DIR"), "/../../dc/s2n-quic-dc/events/**/*.rs" ), output_path: concat!( env!("CARGO_MANIFEST_DIR"), - "/../../dc/s2n-quic-dc/src/event/generated.rs" + "/../../dc/s2n-quic-dc/src/event" ), output_mode: OutputMode::Ref, s2n_quic_core_path: quote!(s2n_quic_core), @@ -130,6 +132,7 @@ impl EventInfo<'_> { }, tracing_subscriber_attr: quote!(), tracing_subscriber_def, + feature_alloc: quote!(), } } } @@ -145,10 +148,17 @@ fn main() -> Result<()> { for path in glob::glob(input_path)? { let path = path?; eprintln!("loading {}", path.canonicalize().unwrap().display()); - let file = std::fs::read_to_string(path)?; - files.push(parser::parse(&file).unwrap()); + let file = std::fs::read_to_string(&path)?; + files.push(parser::parse(&file, path).unwrap()); } + // make sure events are in a deterministic order + files.sort_by(|a, b| a.path.as_os_str().cmp(b.path.as_os_str())); + + let root = std::path::Path::new(event_info.output_path); + let _ = std::fs::create_dir_all(root); + let root = root.canonicalize()?; + let mut output = Output { mode: event_info.output_mode, s2n_quic_core_path: event_info.s2n_quic_core_path, @@ -156,43 +166,13 @@ fn main() -> Result<()> { builders: event_info.builder, tracing_subscriber_attr: event_info.tracing_subscriber_attr, tracing_subscriber_def: event_info.tracing_subscriber_def, + feature_alloc: event_info.feature_alloc, + crate_name: event_info.crate_name, + root, ..Default::default() }; - for file in &files { - file.to_tokens(&mut output); - } - - let generated = std::path::Path::new(event_info.output_path) - .canonicalize() - .unwrap(); - - let mut o = std::fs::File::create(&generated)?; - - macro_rules! put { - ($($arg:tt)*) => {{ - use std::io::Write; - writeln!(o, $($arg)*)?; - }} - } - - put!("// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved."); - put!("// SPDX-License-Identifier: Apache-2.0"); - put!(); - put!("// DO NOT MODIFY THIS FILE"); - put!("// This file was generated with the `s2n-quic-events` crate and any required"); - put!("// changes should be made there."); - put!(); - put!("{}", output.to_token_stream()); - - let status = std::process::Command::new("rustfmt") - .arg(&generated) - .spawn()? - .wait()?; - - assert!(status.success()); - - eprintln!(" wrote {}", generated.display()); + output.generate(&files); } Ok(()) diff --git a/quic/s2n-quic-events/src/output.rs b/quic/s2n-quic-events/src/output.rs index a203b0e82..f68c97f4c 100644 --- a/quic/s2n-quic-events/src/output.rs +++ b/quic/s2n-quic-events/src/output.rs @@ -1,9 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use crate::OutputMode; +use crate::{parser::File, OutputMode}; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use std::path::{Path, PathBuf}; + +pub mod metrics; #[derive(Debug, Default)] pub struct Output { @@ -27,13 +30,60 @@ pub struct Output { pub endpoint_testing_fields_init: TokenStream, pub endpoint_publisher_testing: TokenStream, pub connection_publisher_testing: TokenStream, - pub metrics_fields: TokenStream, - pub metrics_fields_init: TokenStream, - pub metrics_record: TokenStream, - pub subscriber_metrics: TokenStream, pub extra: TokenStream, pub mode: OutputMode, + pub crate_name: &'static str, pub s2n_quic_core_path: TokenStream, + pub top_level: TokenStream, + pub feature_alloc: TokenStream, + pub root: PathBuf, +} + +impl Output { + pub fn generate(&mut self, files: &[File]) { + for file in files { + file.to_tokens(self); + } + + self.top_level.extend(metrics::emit(self, files)); + + self.emit("generated.rs", &self); + } + + pub fn emit, T: ToTokens>(&self, path: P, output: T) { + let path = self.root.join(path); + + let _ = std::fs::create_dir_all(path.parent().unwrap()); + + let mut o = std::fs::File::create(&path).unwrap(); + + macro_rules! put { + ($($arg:tt)*) => {{ + use std::io::Write; + writeln!(o, $($arg)*).unwrap(); + }} + } + + put!("// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved."); + put!("// SPDX-License-Identifier: Apache-2.0"); + put!(); + put!("// DO NOT MODIFY THIS FILE"); + put!("// This file was generated with the `s2n-quic-events` crate and any required"); + put!("// changes should be made there."); + put!(); + put!("{}", output.to_token_stream()); + + let status = std::process::Command::new("rustfmt") + .arg(&path) + .spawn() + .unwrap() + .wait() + .unwrap(); + + assert!(status.success()); + + eprintln!(" wrote {}", path.display()); + } } impl ToTokens for Output { @@ -59,20 +109,19 @@ impl ToTokens for Output { endpoint_testing_fields_init, endpoint_publisher_testing, connection_publisher_testing, - metrics_fields, - metrics_fields_init, - metrics_record, - subscriber_metrics, extra, mode, s2n_quic_core_path, + top_level, + feature_alloc: _, + crate_name, + root: _, } = self; let imports = self.mode.imports(); let mutex = self.mode.mutex(); let testing_output_type = self.mode.testing_output_type(); let lock = self.mode.lock(); - let target_crate = self.mode.target_crate(); let supervisor = self.mode.supervisor(); let supervisor_timeout = self.mode.supervisor_timeout(); let supervisor_timeout_tuple = self.mode.supervisor_timeout_tuple(); @@ -113,6 +162,8 @@ impl ToTokens for Output { tokens.extend(quote!( use super::*; + #top_level + pub mod api { //! This module contains events that are emitted to the [`Subscriber`](crate::event::Subscriber) use super::*; @@ -140,7 +191,7 @@ impl ToTokens for Output { _info: &api::ConnectionInfo ) -> Self::ConnectionContext { let parent = self.parent(meta); - tracing::span!(target: #target_crate, parent: parent, tracing::Level::DEBUG, "conn", id = meta.id) + tracing::span!(target: #crate_name, parent: parent, tracing::Level::DEBUG, "conn", id = meta.id) } #tracing_subscriber @@ -404,54 +455,6 @@ impl ToTokens for Output { } } - pub mod metrics { - use super::*; - #imports - use #s2n_quic_core_path::event::metrics::Recorder; - - #[derive(Debug)] - pub struct Subscriber - where S::ConnectionContext: Recorder { - subscriber: S, - } - - impl Subscriber - where S::ConnectionContext: Recorder { - pub fn new(subscriber: S) -> Self { - Self { subscriber } - } - } - - pub struct Context { - recorder: R, - #metrics_fields - } - - impl super::Subscriber for Subscriber - where S::ConnectionContext: Recorder { - type ConnectionContext = Context; - - fn create_connection_context( - &#mode self, - meta: &api::ConnectionMeta, - info: &api::ConnectionInfo - ) -> Self::ConnectionContext { - Context { - recorder: self.subscriber.create_connection_context(meta, info), - #metrics_fields_init - } - } - - #subscriber_metrics - } - - impl Drop for Context { - fn drop(&mut self) { - #metrics_record - } - } - } - #[cfg(any(test, feature = "testing"))] pub mod testing { use super::*; diff --git a/quic/s2n-quic-events/src/output/metrics.rs b/quic/s2n-quic-events/src/output/metrics.rs new file mode 100644 index 000000000..56d0eb564 --- /dev/null +++ b/quic/s2n-quic-events/src/output/metrics.rs @@ -0,0 +1,129 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use crate::{parser::File, Output}; +use proc_macro2::TokenStream; +use quote::quote; + +mod aggregate; + +pub fn emit(output: &Output, files: &[File]) -> TokenStream { + let events = files + .iter() + .flat_map(|file| file.structs.iter()) + .filter(|s| s.attrs.event_name.is_some()) + .filter(|s| { + // Metrics is only connection-level events + s.attrs.subject.is_connection() + }); + + let mode = &output.mode; + + let imports = output.mode.imports(); + let receiver = output.mode.receiver(); + let counter_increment = output.mode.counter_increment(); + let counter_type = output.mode.counter_type(); + let counter_init = output.mode.counter_init(); + let counter_load = output.mode.counter_load(); + + let mut fields = quote!(); + let mut init = quote!(); + let mut record = quote!(); + let mut subscriber = quote!(); + + for event in events { + let ident = &event.ident; + let counter = event.counter(); + let snake = event.ident_snake(); + let function = event.function(); + let allow_deprecated = &event.attrs.allow_deprecated; + + fields.extend(quote!( + #counter: #counter_type, + )); + init.extend(quote!( + #counter: #counter_init, + )); + + record.extend(quote!( + self.recorder.increment_counter(#snake, self.#counter #counter_load as _); + )); + + subscriber.extend(quote!( + #[inline] + #allow_deprecated + fn #function( + &#receiver self, + context: &#receiver Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::#ident + ) { + context.#counter #counter_increment; + self.subscriber.#function(&#receiver context.recorder, meta, event); + } + )); + } + + let aggregate = aggregate::emit(output, files); + + let tokens = quote!( + #imports + use crate::event::{metrics::Recorder, api, self}; + + #aggregate + + #[derive(Debug)] + pub struct Subscriber + where + S::ConnectionContext: Recorder + { + subscriber: S, + } + + impl Subscriber + where + S::ConnectionContext: Recorder + { + pub fn new(subscriber: S) -> Self { + Self { subscriber } + } + } + + pub struct Context { + recorder: R, + #fields + } + + impl event::Subscriber for Subscriber + where S::ConnectionContext: Recorder { + type ConnectionContext = Context; + + fn create_connection_context( + &#mode self, + meta: &api::ConnectionMeta, + info: &api::ConnectionInfo + ) -> Self::ConnectionContext { + Context { + recorder: self.subscriber.create_connection_context(meta, info), + #init + } + } + + #subscriber + } + + impl Drop for Context { + fn drop(&mut self) { + #record + } + } + ); + + let path = "generated/metrics.rs"; + + output.emit(path, tokens); + + quote!( + pub(crate) mod metrics; + ) +} diff --git a/quic/s2n-quic-events/src/output/metrics/aggregate.rs b/quic/s2n-quic-events/src/output/metrics/aggregate.rs new file mode 100644 index 000000000..b1dd3e7d7 --- /dev/null +++ b/quic/s2n-quic-events/src/output/metrics/aggregate.rs @@ -0,0 +1,491 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + parser::{File, Subject}, + Output, +}; +use proc_macro2::{Ident, Span, TokenStream}; +use quote::{quote, ToTokens}; + +fn new_str(value: impl AsRef) -> TokenStream { + let value_c = format!("{}\0", value.as_ref()); + quote!(new_str(#value_c)) +} + +pub fn emit(output: &Output, files: &[File]) -> TokenStream { + let events = files + .iter() + .flat_map(|file| file.structs.iter()) + .filter(|s| s.attrs.event_name.is_some()) + .filter(|s| s.attrs.allow_deprecated.is_empty()); + + let mode = &output.mode; + + let receiver = output.mode.receiver(); + let s2n_quic_core_path = &output.s2n_quic_core_path; + + let mut subscriber = quote!(); + + let mut info = InfoList::default(); + let mut counters = Registry::new( + quote!(counters), + quote!(register_counter), + format!("{}__event__counter", output.crate_name), + ); + + // TODO allow events to define how to aggregate them + let mut measures = Registry::new( + quote!(measures), + quote!(register_measure), + format!("{}__event__measure", output.crate_name), + ); + let mut gauges = Registry::new( + quote!(gauges), + quote!(register_gauge), + format!("{}__event__gauge", output.crate_name), + ); + let mut timers = Registry::new( + quote!(timers), + quote!(register_timer), + format!("{}__event__timer", output.crate_name), + ); + + for event in events { + let ident = &event.ident; + let snake = event.ident_snake(); + let function = event.function(); + + let mut on_event = quote!(); + + let count_info = &info.push(&snake, ""); + + let count_id = counters.push(count_info); + + on_event.extend(quote!( + self.count(#count_info, #count_id, 1); + )); + + match event.attrs.subject { + Subject::Connection => { + subscriber.extend(quote!( + #[inline] + fn #function( + &#receiver self, + context: &#receiver Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::#ident + ) { + #on_event + let _ = context; + let _ = meta; + let _ = event; + } + )); + } + Subject::Endpoint => { + subscriber.extend(quote!( + #[inline] + fn #function( + &#receiver self, + meta: &api::EndpointMeta, + event: &api::#ident + ) { + #on_event + let _ = event; + let _ = meta; + } + )); + } + } + } + + let counters_init = counters.init(); + let counters_probes = counters.probe(); + let counters_len = counters.len; + let measures_init = measures.init(); + let measures_probes = measures.probe(); + let measures_len = measures.len; + let gauges_init = gauges.init(); + let gauges_probes = gauges.probe(); + let gauges_len = gauges.len; + let timers_init = timers.init(); + let timers_probes = timers.probe(); + let timers_len = timers.len; + let info_len = info.len; + let mut imports = quote!(); + + if !output.feature_alloc.is_empty() { + imports.extend(quote!( + use alloc::{vec::Vec, boxed::Box}; + )); + } + + let tokens = quote!( + #imports + use crate::event::{metrics::aggregate::{Registry, Recorder, Info, info}, api, self}; + + const fn new_str(bytes: &'static str) -> info::Str<'static> { + unsafe { + info::Str::new_unchecked(bytes) + } + } + + static INFO: &[Info; #info_len] = &[#info]; + + pub struct Subscriber { + #[allow(dead_code)] + counters: Box<[R::Counter]>, + #[allow(dead_code)] + measures: Box<[R::Measure]>, + #[allow(dead_code)] + gauges: Box<[R::Gauge]>, + #[allow(dead_code)] + timers: Box<[R::Timer]>, + #[allow(dead_code)] + registry: R, + } + + impl Default for Subscriber { + fn default() -> Self { + Self::new(R::default()) + } + } + + impl Subscriber { + /// Creates a new subscriber with the given registry + /// + /// # Note + /// + /// All of the recorders are registered on initialization and cached for the lifetime + /// of the subscriber. + #[allow(unused_mut)] + #[inline] + pub fn new(registry: R) -> Self { + let mut counters = Vec::with_capacity(#counters_len); + let mut measures = Vec::with_capacity(#measures_len); + let mut gauges = Vec::with_capacity(#gauges_len); + let mut timers = Vec::with_capacity(#timers_len); + + #counters_init + #measures_init + #gauges_init + #timers_init + + Self { + counters: counters.into(), + measures: measures.into(), + gauges: gauges.into(), + timers: timers.into(), + registry, + } + } + + /// Returns all of the registered counters + #[inline] + pub fn counters(&self) -> impl Iterator + '_ { + #counters + } + + #[allow(dead_code)] + #[inline(always)] + fn count(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let counter = unsafe { self.counters.get_unchecked(id) }; + counter.record(info, value); + } + + /// Returns all of the registered measures + #[inline] + pub fn measures(&self) -> impl Iterator + '_ { + #measures + } + + #[allow(dead_code)] + #[inline(always)] + fn measure(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let measure = unsafe { self.measures.get_unchecked(id) }; + measure.record(info, value); + } + + /// Returns all of the registered gauges + #[inline] + pub fn gauges(&self) -> impl Iterator + '_ { + #gauges + } + + #[allow(dead_code)] + #[inline(always)] + fn gauge(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let gauge = unsafe { self.gauges.get_unchecked(id) }; + gauge.record(info, value); + } + + /// Returns all of the registered timers + #[inline] + pub fn timers(&self) -> impl Iterator + '_ { + #timers + } + + #[allow(dead_code)] + #[inline(always)] + fn time(&self, info: usize, id: usize, value: u64) { + let info = unsafe { INFO.get_unchecked(info) }; + let timer = unsafe { self.timers.get_unchecked(id) }; + timer.record(info, value); + } + } + + impl event::Subscriber for Subscriber { + // TODO include some per-connection context to get aggregates for those + type ConnectionContext = (); + + fn create_connection_context( + &#mode self, + _meta: &api::ConnectionMeta, + _info: &api::ConnectionInfo + ) -> Self::ConnectionContext {} + + #subscriber + } + ); + + let probe = quote!( + use #s2n_quic_core_path::probe::define; + use crate::event::metrics::aggregate::{self, Recorder, Info}; + + mod counter { + #counters_probes + } + mod measure { + #measures_probes + } + mod gauge { + #gauges_probes + } + mod timer { + #timers_probes + } + + #[derive(Default)] + pub struct Registry(()); + + impl aggregate::Registry for Registry { + type Counter = counter::Recorder; + type Measure = measure::Recorder; + type Gauge = gauge::Recorder; + type Timer = timer::Recorder; + + #[inline] + fn register_counter(&self, info: &'static Info) -> Self::Counter { + counter::Recorder::new(info) + } + + #[inline] + fn register_measure(&self, info: &'static Info) -> Self::Measure { + measure::Recorder::new(info) + } + + #[inline] + fn register_gauge(&self, info: &'static Info) -> Self::Gauge { + gauge::Recorder::new(info) + } + + #[inline] + fn register_timer(&self, info: &'static Info) -> Self::Timer { + timer::Recorder::new(info) + } + } + ); + + output.emit("generated/metrics/aggregate.rs", tokens); + output.emit("generated/metrics/probe.rs", probe); + + let feature_alloc = &output.feature_alloc; + quote!( + #feature_alloc + pub(crate) mod aggregate; + pub(crate) mod probe; + ) +} + +#[derive(Default)] +struct InfoList { + len: usize, + entries: TokenStream, +} + +impl InfoList { + pub fn push(&mut self, name: impl AsRef, units: impl AsRef) -> Info { + let id = self.len; + self.len += 1; + + let name = name.as_ref(); + let name_t = new_str(name); + let units_t = new_str(units); + + let entry = quote!( + info::Builder { + id: #id, + name: #name_t, + units: #units_t, + }.build(), + ); + + self.entries.extend(entry); + + Info { + idx: id, + name: name.to_string(), + } + } +} + +impl ToTokens for InfoList { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.entries.to_tokens(tokens); + } +} + +#[derive(Debug)] +struct Info { + idx: usize, + name: String, +} + +impl ToTokens for Info { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.idx.to_tokens(tokens); + } +} + +struct Registry { + len: usize, + dest: TokenStream, + register: TokenStream, + init: TokenStream, + probe_path: String, + probe_new: TokenStream, + probe_defs: TokenStream, + entries: TokenStream, +} + +impl Registry { + pub fn new(dest: TokenStream, register: TokenStream, probe_path: String) -> Self { + Self { + len: 0, + dest, + register, + init: quote!(), + probe_path, + probe_new: quote!(), + probe_defs: quote!(), + entries: quote!(), + } + } + + pub fn init(&mut self) -> TokenStream { + self.init.clone() + } + + pub fn probe(&self) -> TokenStream { + let probe_new = &self.probe_new; + + let probe_new = if probe_new.is_empty() { + quote!(unreachable!("invalid info: {info:?}")) + } else { + quote!( + match info.id { + #probe_new + _ => unreachable!("invalid info: {info:?}"), + } + ) + }; + + let probe_defs = &self.probe_defs; + let probe_defs = if probe_defs.is_empty() { + quote!() + } else { + quote!(super::define!( + extern "probe" { + #probe_defs + } + );) + }; + + quote!( + use super::Info; + + pub struct Recorder(fn(u64)); + + impl Recorder { + pub(super) fn new(info: &'static Info) -> Self { + #probe_new + } + } + + impl super::Recorder for Recorder { + fn record(&self, _info: &'static Info, value: u64) { + (self.0)(value); + } + } + + #probe_defs + ) + } + + pub fn push(&mut self, info: &Info) -> usize { + let id = self.len; + self.len += 1; + + let dest = &self.dest; + let register = &self.register; + + self.init.extend(quote!( + #dest.push(registry.#register(&INFO[#info])); + )); + + self.entries.extend(quote!( + #id => (&INFO[#info], entry), + )); + + let probe = &Ident::new(&info.name, Span::call_site()); + let link_name = &Ident::new( + &format!("{}__{}", self.probe_path, info.name), + Span::call_site(), + ); + + self.probe_new.extend(quote!( + #id => Self(#probe), + )); + + self.probe_defs.extend(quote!( + #[link_name = #link_name] + fn #probe(value: u64); + )); + + id + } +} + +impl ToTokens for Registry { + fn to_tokens(&self, tokens: &mut TokenStream) { + if self.len == 0 { + tokens.extend(quote!(core::iter::empty())); + return; + } + + let dest = &self.dest; + let entries = &self.entries; + tokens.extend(quote!( + self.#dest.iter().enumerate().map(|(idx, entry)| { + match idx { + #entries + _ => unsafe { core::hint::unreachable_unchecked() }, + } + }) + )); + } +} diff --git a/quic/s2n-quic-events/src/output_mode.rs b/quic/s2n-quic-events/src/output_mode.rs index b1e283511..b04df4b16 100644 --- a/quic/s2n-quic-events/src/output_mode.rs +++ b/quic/s2n-quic-events/src/output_mode.rs @@ -88,13 +88,6 @@ impl OutputMode { } } - pub fn target_crate(&self) -> TokenStream { - match self { - OutputMode::Ref => quote!("s2n_quic_dc"), - OutputMode::Mut => quote!("s2n_quic"), - } - } - pub fn trait_constraints(&self) -> TokenStream { match self { OutputMode::Ref => quote!('static + Send + Sync), diff --git a/quic/s2n-quic-events/src/parser.rs b/quic/s2n-quic-events/src/parser.rs index 08472e945..53737dda8 100644 --- a/quic/s2n-quic-events/src/parser.rs +++ b/quic/s2n-quic-events/src/parser.rs @@ -5,24 +5,35 @@ use crate::{Output, Result}; use heck::ToSnakeCase; use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; +use std::path::PathBuf; use syn::{ parse::{Parse, ParseStream}, Meta, }; +pub fn parse(contents: &str, path: PathBuf) -> Result { + let file = syn::parse_str(contents)?; + let common = File::parse(file, path); + Ok(common) +} + #[derive(Debug, Default)] pub struct File { pub structs: Vec, pub enums: Vec, pub extra: TokenStream, + pub path: PathBuf, } impl File { - fn parse(file: syn::File) -> Self { + fn parse(file: syn::File, path: PathBuf) -> Self { assert!(file.attrs.is_empty()); assert!(file.shebang.is_none()); - let mut out = File::default(); + let mut out = File { + path, + ..Default::default() + }; for item in file.items { match item { syn::Item::Enum(v) => out.enums.push(Enum::parse(v)), @@ -47,10 +58,10 @@ impl File { #[derive(Debug)] pub struct Struct { - attrs: ContainerAttrs, - ident: syn::Ident, - generics: syn::Generics, - fields: Vec, + pub attrs: ContainerAttrs, + pub ident: syn::Ident, + pub generics: syn::Generics, + pub fields: Vec, } impl Struct { @@ -65,6 +76,26 @@ impl Struct { } } + pub fn ident_str(&self) -> String { + self.ident.to_string() + } + + pub fn ident_snake(&self) -> String { + self.ident_str().to_snake_case() + } + + pub fn function_name(&self) -> String { + format!("on_{}", self.ident_snake()) + } + + pub fn function(&self) -> Ident { + Ident::new(&self.function_name(), Span::call_site()) + } + + pub fn counter(&self) -> Ident { + Ident::new(&self.ident_snake(), Span::call_site()) + } + fn to_tokens(&self, output: &mut Output) { let Self { attrs, @@ -150,11 +181,10 @@ impl Struct { } )); - let ident_str = ident.to_string(); - let snake = ident_str.to_snake_case(); - let function = format!("on_{snake}"); - let counter = Ident::new(&snake, Span::call_site()); - let function = Ident::new(&function, Span::call_site()); + let ident_str = self.ident_str(); + let snake = self.ident_snake(); + let counter = self.counter(); + let function = self.function(); let subscriber_doc = format!("Called when the `{ident_str}` event is triggered"); let publisher_doc = @@ -162,7 +192,6 @@ impl Struct { let counter_type = output.mode.counter_type(); let counter_init = output.mode.counter_init(); - let counter_load = output.mode.counter_load(); // add a counter for testing structs output.testing_fields.extend(quote!( @@ -346,32 +375,6 @@ impl Struct { } )); - // Metrics is only connection-level events - output.metrics_fields.extend(quote!( - #counter: #counter_type, - )); - output.metrics_fields_init.extend(quote!( - #counter: #counter_init, - )); - - output.metrics_record.extend(quote!( - self.recorder.increment_counter(#snake, self.#counter #counter_load as _); - )); - - output.subscriber_metrics.extend(quote!( - #[inline] - #allow_deprecated - fn #function( - &#receiver self, - context: &#receiver Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::#ident - ) { - context.#counter #counter_increment; - self.subscriber.#function(&#receiver context.recorder, meta, event); - } - )); - output.subscriber_testing.extend(quote!( #allow_deprecated fn #function( @@ -410,10 +413,10 @@ impl Struct { #[derive(Debug)] pub struct Enum { - attrs: ContainerAttrs, - ident: syn::Ident, - generics: syn::Generics, - variants: Vec, + pub attrs: ContainerAttrs, + pub ident: syn::Ident, + pub generics: syn::Generics, + pub variants: Vec, } impl Enum { @@ -496,17 +499,17 @@ impl Enum { } #[derive(Debug)] -struct ContainerAttrs { - event_name: Option, - deprecated: TokenStream, - allow_deprecated: TokenStream, - subject: Subject, - exhaustive: bool, - derive: bool, - derive_attrs: TokenStream, - builder_derive: bool, - builder_derive_attrs: TokenStream, - extra: TokenStream, +pub struct ContainerAttrs { + pub event_name: Option, + pub deprecated: TokenStream, + pub allow_deprecated: TokenStream, + pub subject: Subject, + pub exhaustive: bool, + pub derive: bool, + pub derive_attrs: TokenStream, + pub builder_derive: bool, + pub builder_derive_attrs: TokenStream, + pub extra: TokenStream, } impl ContainerAttrs { @@ -559,11 +562,23 @@ impl ContainerAttrs { } #[derive(Debug)] -enum Subject { +pub enum Subject { Connection, Endpoint, } +impl Subject { + #[allow(dead_code)] + pub fn is_connection(&self) -> bool { + matches!(self, Self::Connection) + } + + #[allow(dead_code)] + pub fn is_endpoint(&self) -> bool { + matches!(self, Self::Endpoint) + } +} + impl Parse for Subject { fn parse(input: ParseStream) -> syn::parse::Result { let name: Ident = input.parse()?; @@ -579,10 +594,10 @@ impl Parse for Subject { } #[derive(Debug)] -struct Field { - attrs: FieldAttrs, - ident: Option, - ty: syn::Type, +pub struct Field { + pub attrs: FieldAttrs, + pub ident: Option, + pub ty: syn::Type, } impl Field { @@ -675,10 +690,10 @@ impl Field { } #[derive(Debug)] -struct FieldAttrs { - builder: Option, - snapshot: Option, - extra: TokenStream, +pub struct FieldAttrs { + pub builder: Option, + pub snapshot: Option, + pub extra: TokenStream, } impl FieldAttrs { @@ -705,10 +720,10 @@ impl FieldAttrs { } #[derive(Debug)] -struct Variant { - ident: syn::Ident, - attrs: Vec, - fields: Vec, +pub struct Variant { + pub ident: syn::Ident, + pub attrs: Vec, + pub fields: Vec, } impl Variant { @@ -760,9 +775,3 @@ impl Variant { } } } - -pub fn parse(contents: &str) -> Result { - let file = syn::parse_str(contents)?; - let common = File::parse(file); - Ok(common) -}