// Copyright (C) 2021, Cloudflare, Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// A helper object specialized for streaming JSON-serialized qlog to a /// [`Write`] trait. /// /// The object is responsible for the `Qlog` object that contains the /// provided `Trace`. /// /// Serialization is progressively driven by method calls; once log streaming /// is started, `event::Events` can be written using `add_event()`. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html usesuper::*;
/// Finishes qlog streaming serialization. /// /// After this is called, no more serialization will occur. pubfn finish_log(&mutself) -> Result<()> { ifself.state == StreamerState::Initial || self.state == StreamerState::Finished
{ return Err(Error::InvalidState);
}
self.state = StreamerState::Finished;
self.writer.as_mut().flush()?;
Ok(())
}
/// Writes a serializable to a JSON-SEQ record using /// [std::time::Instant::now()]. pubfn add_event_now<E: Serialize + Eventable>(
&mutself, event: E,
) -> Result<()> { let now = std::time::Instant::now();
self.add_event_with_instant(event, now)
}
/// Writes a serializable to a JSON-SEQ record using the provided /// [std::time::Instant]. pubfn add_event_with_instant<E: Serialize + Eventable>(
&mutself, mut event: E, now: std::time::Instant,
) -> Result<()> { ifself.state != StreamerState::Ready { return Err(Error::InvalidState);
}
if !event.importance().is_contained_in(&self.log_level) { return Err(Error::Done);
}
let dur = if cfg!(test) {
std::time::Duration::from_secs(0)
} else {
now.duration_since(self.start_time)
};
let rel_time = dur.as_secs_f32() * 1000.0;
event.set_time(rel_time);
self.add_event(event)
}
/// Writes an [Event] based on the provided [EventData] to a JSON-SEQ record /// at time [std::time::Instant::now()]. pubfn add_event_data_now(&mutself, event_data: EventData) -> Result<()> { self.add_event_data_ex_now(event_data, Default::default())
}
/// Writes an [Event] based on the provided [EventData] and [ExData] to a /// JSON-SEQ record at time [std::time::Instant::now()]. pubfn add_event_data_ex_now(
&mutself, event_data: EventData, ex_data: ExData,
) -> Result<()> { let now = std::time::Instant::now();
/// Writes an [Event] based on the provided [EventData] and /// [std::time::Instant] to a JSON-SEQ record. pubfn add_event_data_with_instant(
&mutself, event_data: EventData, now: std::time::Instant,
) -> Result<()> { self.add_event_data_ex_with_instant(event_data, Default::default(), now)
}
/// Writes an [Event] based on the provided [EventData], [ExData], and /// [std::time::Instant] to a JSON-SEQ record. pubfn add_event_data_ex_with_instant(
&mutself, event_data: EventData, ex_data: ExData,
now: std::time::Instant,
) -> Result<()> { ifself.state != StreamerState::Ready { return Err(Error::InvalidState);
}
let ty = EventType::from(&event_data); if !EventImportance::from(ty).is_contained_in(&self.log_level) { return Err(Error::Done);
}
let dur = if cfg!(test) {
std::time::Duration::from_secs(0)
} else {
now.duration_since(self.start_time)
};
let rel_time = dur.as_secs_f32() * 1000.0; let event = Event::with_time_ex(rel_time, event_data, ex_data);
self.add_event(event)
}
/// Writes a JSON-SEQ-serialized [Event] using the provided [Event]. pubfn add_event<E: Serialize + Eventable>(
&mutself, event: E,
) -> Result<()> { ifself.state != StreamerState::Ready { return Err(Error::InvalidState);
}
if !event.importance().is_contained_in(&self.log_level) { return Err(Error::Done);
}
impl Drop for QlogStreamer { fn drop(&mutself) { let _ = self.finish_log();
}
}
#[cfg(test)] mod tests { use std::collections::BTreeMap;
usesuper::*; usecrate::events::quic; usecrate::events::quic::QuicFrame; usecrate::events::RawInfo; use smallvec::smallvec; use testing::*;
use serde_json::json;
#[test] fn serialization_states() { let v: Vec<u8> = Vec::new(); let buff = std::io::Cursor::new(v); let writer = Box::new(buff);
let trace = make_trace_seq(); let pkt_hdr = make_pkt_hdr(quic::PacketType::Handshake); let raw = Some(RawInfo {
length: Some(1251),
payload_length: Some(1224),
data: None,
});
// Before the log is started all other operations should fail.
assert!(matches!(s.add_event(ev2.clone()), Err(Error::InvalidState)));
assert!(matches!(s.finish_log(), Err(Error::InvalidState)));
// Start log and add a simple event.
assert!(matches!(s.start_log(), Ok(())));
assert!(matches!(s.add_event(ev1), Ok(())));
// Add some more events.
assert!(matches!(s.add_event(ev2), Ok(())));
assert!(matches!(s.add_event(ev3.clone()), Ok(())));
// Adding an event with an external time should work too. // For tests, it will resolve to 0 but we care about proving the API // here, not timing specifics. let now = std::time::Instant::now();
let written_string = std::str::from_utf8(w.as_ref().get_ref()).unwrap();
assert_eq!(log_string, written_string);
}
#[test] fn stream_data_ex() { let v: Vec<u8> = Vec::new(); let buff = std::io::Cursor::new(v); let writer = Box::new(buff);
let trace = make_trace_seq(); let pkt_hdr = make_pkt_hdr(quic::PacketType::Handshake); let raw = Some(RawInfo {
length: Some(1251),
payload_length: Some(1224),
data: None,
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.