summaryrefslogtreecommitdiffstats
path: root/third_party/rust/neqo-common/src/qlog.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/neqo-common/src/qlog.rs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/neqo-common/src/qlog.rs')
-rw-r--r--third_party/rust/neqo-common/src/qlog.rs188
1 files changed, 188 insertions, 0 deletions
diff --git a/third_party/rust/neqo-common/src/qlog.rs b/third_party/rust/neqo-common/src/qlog.rs
new file mode 100644
index 0000000000..3da8350990
--- /dev/null
+++ b/third_party/rust/neqo-common/src/qlog.rs
@@ -0,0 +1,188 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+ cell::RefCell,
+ fmt,
+ path::{Path, PathBuf},
+ rc::Rc,
+};
+
+use qlog::{
+ self, streamer::QlogStreamer, CommonFields, Configuration, TraceSeq, VantagePoint,
+ VantagePointType,
+};
+
+use crate::Role;
+
+#[allow(clippy::module_name_repetitions)]
+#[derive(Debug, Clone, Default)]
+pub struct NeqoQlog {
+ inner: Rc<RefCell<Option<NeqoQlogShared>>>,
+}
+
+pub struct NeqoQlogShared {
+ qlog_path: PathBuf,
+ streamer: QlogStreamer,
+}
+
+impl NeqoQlog {
+ /// Create an enabled `NeqoQlog` configuration.
+ ///
+ /// # Errors
+ ///
+ /// Will return `qlog::Error` if cannot write to the new log.
+ pub fn enabled(
+ mut streamer: QlogStreamer,
+ qlog_path: impl AsRef<Path>,
+ ) -> Result<Self, qlog::Error> {
+ streamer.start_log()?;
+
+ Ok(Self {
+ inner: Rc::new(RefCell::new(Some(NeqoQlogShared {
+ streamer,
+ qlog_path: qlog_path.as_ref().to_owned(),
+ }))),
+ })
+ }
+
+ #[must_use]
+ pub fn inner(&self) -> Rc<RefCell<Option<NeqoQlogShared>>> {
+ Rc::clone(&self.inner)
+ }
+
+ /// Create a disabled `NeqoQlog` configuration.
+ #[must_use]
+ pub fn disabled() -> Self {
+ Self::default()
+ }
+
+ /// If logging enabled, closure may generate an event to be logged.
+ pub fn add_event<F>(&mut self, f: F)
+ where
+ F: FnOnce() -> Option<qlog::events::Event>,
+ {
+ self.add_event_with_stream(|s| {
+ if let Some(evt) = f() {
+ s.add_event(evt)?;
+ }
+ Ok(())
+ });
+ }
+
+ /// If logging enabled, closure may generate an event to be logged.
+ pub fn add_event_data<F>(&mut self, f: F)
+ where
+ F: FnOnce() -> Option<qlog::events::EventData>,
+ {
+ self.add_event_with_stream(|s| {
+ if let Some(ev_data) = f() {
+ s.add_event_data_now(ev_data)?;
+ }
+ Ok(())
+ });
+ }
+
+ /// If logging enabled, closure is given the Qlog stream to write events and
+ /// frames to.
+ pub fn add_event_with_stream<F>(&mut self, f: F)
+ where
+ F: FnOnce(&mut QlogStreamer) -> Result<(), qlog::Error>,
+ {
+ if let Some(inner) = self.inner.borrow_mut().as_mut() {
+ if let Err(e) = f(&mut inner.streamer) {
+ crate::do_log!(
+ ::log::Level::Error,
+ "Qlog event generation failed with error {}; closing qlog.",
+ e
+ );
+ *self.inner.borrow_mut() = None;
+ }
+ }
+ }
+}
+
+impl fmt::Debug for NeqoQlogShared {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "NeqoQlog writing to {}", self.qlog_path.display())
+ }
+}
+
+impl Drop for NeqoQlogShared {
+ fn drop(&mut self) {
+ if let Err(e) = self.streamer.finish_log() {
+ crate::do_log!(::log::Level::Error, "Error dropping NeqoQlog: {}", e);
+ }
+ }
+}
+
+#[must_use]
+pub fn new_trace(role: Role) -> qlog::TraceSeq {
+ TraceSeq {
+ vantage_point: VantagePoint {
+ name: Some(format!("neqo-{role}")),
+ ty: match role {
+ Role::Client => VantagePointType::Client,
+ Role::Server => VantagePointType::Server,
+ },
+ flow: None,
+ },
+ title: Some(format!("neqo-{role} trace")),
+ description: Some("Example qlog trace description".to_string()),
+ configuration: Some(Configuration {
+ time_offset: Some(0.0),
+ original_uris: None,
+ }),
+ common_fields: Some(CommonFields {
+ group_id: None,
+ protocol_type: None,
+ reference_time: {
+ // It is better to allow this than deal with a conversion from i64 to f64.
+ // We can't do the obvious two-step conversion with f64::from(i32::try_from(...)),
+ // because that overflows earlier than is ideal. This should be fine for a while.
+ #[allow(clippy::cast_precision_loss)]
+ Some(time::OffsetDateTime::now_utc().unix_timestamp() as f64)
+ },
+ time_format: Some("relative".to_string()),
+ }),
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use qlog::events::Event;
+ use test_fixture::EXPECTED_LOG_HEADER;
+
+ const EV_DATA: qlog::events::EventData =
+ qlog::events::EventData::SpinBitUpdated(qlog::events::connectivity::SpinBitUpdated {
+ state: true,
+ });
+
+ const EXPECTED_LOG_EVENT: &str = concat!(
+ "\u{1e}",
+ r#"{"time":0.0,"name":"connectivity:spin_bit_updated","data":{"state":true}}"#,
+ "\n"
+ );
+
+ #[test]
+ fn new_neqo_qlog() {
+ let (_log, contents) = test_fixture::new_neqo_qlog();
+ assert_eq!(contents.to_string(), EXPECTED_LOG_HEADER);
+ }
+
+ #[test]
+ fn add_event() {
+ let (mut log, contents) = test_fixture::new_neqo_qlog();
+ log.add_event(|| Some(Event::with_time(1.1, EV_DATA)));
+ assert_eq!(
+ contents.to_string(),
+ format!(
+ "{EXPECTED_LOG_HEADER}{e}",
+ e = EXPECTED_LOG_EVENT.replace("\"time\":0.0,", "\"time\":1.1,")
+ )
+ );
+ }
+}