Skip to content

Commit

Permalink
Document the streaming serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
LPardue committed Mar 24, 2020
1 parent 26dc338 commit aef9237
Showing 1 changed file with 129 additions and 9 deletions.
138 changes: 129 additions & 9 deletions tools/qlog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ The crate uses Serde for conversion between Rust and JSON.
[qlog QUIC and HTTP/3 events]: https://quiclog.github.io/internet-drafts/draft-marx-qlog-event-definitions-quic-h3
[TypeScript schema]: https://github.com/quiclog/qlog/blob/master/TypeScript/draft-01/QLog.ts

Getting Started
---------------
Overview
--------

An application will typically want to create a qlog for each QUIC connection. As
events occur doing the connection they are appended to the trace. The qlog crate
supports two modes of writing logs: the buffered mode stores everything in
memory and requires the application to serialize and write the output, the
streaming mode progressively writes serialized JSON output to a writer
designated by the application.

### Creating a trace
Buffered Mode
---------------

A typical application needs a single qlog trace that it appends QUIC and/or
HTTP/3 events to:
Create the trace:

```rust
let trace = Trace {
Expand Down Expand Up @@ -63,7 +70,7 @@ trace.push_transport_event(
packet_number: "0".to_string(),
packet_size: Some(1251),
payload_length: Some(1224),
version: Some("0xff000018".to_string()),
version: Some("0xff00001b".to_string()),
scil: Some("8".to_string()),
dcil: Some("8".to_string()),
scid: Some("7e37e4dcc6682da8".to_string()),
Expand All @@ -82,13 +89,15 @@ trace.push_transport_event(

### Serializing

Simply:
The qlog crate has only been tested with `serde_json`, however other serializer targets might work.

For example, serializing the trace created above:

```rust
serde_json::to_string_pretty(&trace).unwrap();
```

which would generate the following:
would generate the following:

```
{
Expand Down Expand Up @@ -119,7 +128,7 @@ which would generate the following:
"packet_number": "0",
"packet_size": 1251,
"payload_length": 1224,
"version": "0xff000018",
"version": "0xff00001b",
"scil": "8",
"dcil": "8",
"scid": "7e37e4dcc6682da8",
Expand All @@ -137,3 +146,114 @@ which would generate the following:
]
}
```

Streaming Mode
---------------

Create the trace:

```rust
let trace = Trace {
vantage_point: VantagePoint {
name: "Example client",
ty: VantagePointType::Client,
flow: None,
},
title: Some("Example qlog trace".to_string()),
description: Some("Example qlog trace description".to_string()),
configuration: Some(Configuration {
time_offset: Some("0".to_string()),
time_units: Some(TimeUnits::Ms),
original_uris: None,
}),
common_fields: None,
event_fields: vec![
"relative_time".to_string(),
"category".to_string(),
"event".to_string(),
"data".to_string(),
],
events: Vec::new(),
};

```

Create an object with the `Write` trait:

```rustSome(description),Some(description),
let mut file = std::fs::File::create("foo.qlog").ok();
```

Create a `QlogStreamer` and start serialization to foo.qlog:

```rust
let mut streamer = qlog::QlogStreamer::new(
qlog::QLOG_VERSION.to_string(),
Some("Example qlog".to_string()),
Some("Example qlog description".to_string()),
None,
std::time::Instant::now(),
trace,
Box::new(file),
);

streamer.start_log().ok();

```

### Adding events

Once logging has started you can stream events. Simple events can be written in one step:

```rust
let event = qlog::Event::metrics_updated_min();
streamer.add_event(event).ok();
```

Some events contain optional arrays of QUIC frames. If the event has `Some(Vec<QuicFrame>)`, even if it is empty, the streamer enters a frame serializing mode that must be finalized before other events can be logged.

In this example, a Packet Sent event is created with an empty frame array and frames are written out later:

```rust
let qlog_pkt_hdr = qlog::PacketHeader::with_type(
qlog::PacketType::OneRtt,
0,
Some(1251),
Some(1224),
Some(0xff00001b),
Some(b"7e37e4dcc6682da8"),
Some(b"36ce104eee50101c"),
);

let packet_sent_ev = Event::packet_sent_min(
qlog::PacketType::OneRtt,
qlog_pkt_hdr,
Some(Vec::new()),
);

streamer.add_event(event).ok();

```

The frames contained in the QUIC packet are PING and PADDING. Once these are streamed, frame writing is concluded:

```rust
let ping = qlog::QuicFrame::ping();
let padding = qlog::QuicFrame::padding();

streamer.add_frame(ping, false).ok();
streamer.add_frame(padding, false).ok();

streamer.finish_frames().ok();
```

Once all events have have been written, the log can be finalized:

```rust
steamer.finish_log().ok();
```

### Serializing

Serlization to JSON occurs as methods on the `QlogStreamer` are called. No
additional steps are required.

0 comments on commit aef9237

Please sign in to comment.