├── .github ├── CODEOWNERS ├── in-solidarity.yml └── workflows │ ├── archive.yml │ ├── cddl_validate.yml │ ├── ghpages.yml │ └── publish.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE.md ├── Makefile ├── README.md ├── cddl_validate.sh ├── draft-ietf-quic-qlog-h3-events.md ├── draft-ietf-quic-qlog-main-schema.md └── draft-ietf-quic-qlog-quic-events.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @rmarx @marten-seemann @lnicco @LPardue -------------------------------------------------------------------------------- /.github/in-solidarity.yml: -------------------------------------------------------------------------------- 1 | _extends: ietf/terminology 2 | -------------------------------------------------------------------------------- /.github/workflows/archive.yml: -------------------------------------------------------------------------------- 1 | name: "Archive Issues and Pull Requests" 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 0,2,4' 6 | repository_dispatch: 7 | types: [archive] 8 | 9 | jobs: 10 | build: 11 | name: "Archive Issues and Pull Requests" 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: "Checkout" 15 | uses: actions/checkout@v4 16 | 17 | - name: "Update Archive" 18 | uses: martinthomson/i-d-template@v1 19 | with: 20 | make: archive 21 | token: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | - name: "Update GitHub Pages" 24 | uses: martinthomson/i-d-template@v1 25 | with: 26 | make: gh-archive 27 | token: ${{ secrets.GITHUB_TOKEN }} 28 | 29 | - name: "Save Archive" 30 | uses: actions/upload-artifact@v4 31 | with: 32 | path: archive.json 33 | -------------------------------------------------------------------------------- /.github/workflows/cddl_validate.yml: -------------------------------------------------------------------------------- 1 | name: CDDL Validation 2 | 3 | on: [push, pull_request] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | validate: 10 | name: "Validates CDDL for all documents" 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | ruby-version: ['3.3.0'] 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Apt update 19 | run: sudo apt update 20 | - name: Install System Dependencies 21 | run: sudo apt-get install --yes libyaml-dev openssl 22 | - name: Set up Ruby 23 | uses: ruby/setup-ruby@v1 24 | with: 25 | ruby-version: ${{ matrix.ruby-version }} 26 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 27 | - name: Install Ruby gems 28 | run: gem install cddl 29 | - name: validate CDDL (main schema) 30 | run: ./cddl_validate.sh draft-ietf-quic-qlog-main-schema.md 31 | - name: validate CDDL (quic events) 32 | if: success() || failure() 33 | run: ./cddl_validate.sh draft-ietf-quic-qlog-quic-events.md 34 | - name: validate CDDL (h3 events) 35 | if: success() || failure() 36 | run: ./cddl_validate.sh draft-ietf-quic-qlog-h3-events.md 37 | -------------------------------------------------------------------------------- /.github/workflows/ghpages.yml: -------------------------------------------------------------------------------- 1 | name: "Update Editor's Copy" 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - README.md 7 | - CONTRIBUTING.md 8 | - LICENSE.md 9 | - .gitignore 10 | pull_request: 11 | paths-ignore: 12 | - README.md 13 | - CONTRIBUTING.md 14 | - LICENSE.md 15 | - .gitignore 16 | 17 | jobs: 18 | build: 19 | name: "Update Editor's Copy" 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: "Checkout" 23 | uses: actions/checkout@v4 24 | 25 | - name: Install System Dependencies 26 | run: sudo apt-get install --yes libyaml-dev openssl ruby-dev 27 | 28 | - name: "Cache Setup" 29 | id: cache-setup 30 | run: | 31 | mkdir -p "$HOME"/.cache/xml2rfc 32 | echo "::set-output name=path::$HOME/.cache/xml2rfc" 33 | date -u "+::set-output name=date::%FT%T" 34 | 35 | - name: "Cache References" 36 | uses: actions/cache@v4 37 | with: 38 | path: | 39 | ${{ steps.cache-setup.outputs.path }} 40 | .targets.mk 41 | key: refcache-${{ steps.cache-setup.outputs.date }} 42 | restore-keys: | 43 | refcache-${{ steps.cache-setup.outputs.date }} 44 | refcache- 45 | 46 | - name: "Build Drafts" 47 | uses: martinthomson/i-d-template@v1 48 | 49 | - name: "Update GitHub Pages" 50 | uses: martinthomson/i-d-template@v1 51 | if: ${{ github.event_name == 'push' }} 52 | with: 53 | make: gh-pages 54 | token: ${{ secrets.GITHUB_TOKEN }} 55 | 56 | - name: "Archive Built Drafts" 57 | uses: actions/upload-artifact@v4 58 | with: 59 | path: | 60 | draft-*.html 61 | draft-*.txt 62 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "Publish New Draft Version" 2 | 3 | on: 4 | push: 5 | tags: 6 | - "draft-*" 7 | 8 | jobs: 9 | build: 10 | name: "Publish New Draft Version" 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: "Checkout" 14 | uses: actions/checkout@v4 15 | 16 | # See https://github.com/actions/checkout/issues/290 17 | - name: "Get Tag Annotations" 18 | run: git fetch -f origin ${{ github.ref }}:${{ github.ref }} 19 | 20 | - name: "Cache Setup" 21 | id: cache-setup 22 | run: | 23 | mkdir -p "$HOME"/.cache/xml2rfc 24 | echo "::set-output name=path::$HOME/.cache/xml2rfc" 25 | date -u "+::set-output name=date::%FT%T" 26 | 27 | - name: "Cache References" 28 | uses: actions/cache@v4 29 | with: 30 | path: | 31 | ${{ steps.cache-setup.outputs.path }} 32 | .targets.mk 33 | key: refcache-${{ steps.date.outputs.date }} 34 | restore-keys: | 35 | refcache-${{ steps.date.outputs.date }} 36 | refcache- 37 | 38 | - name: "Build Drafts" 39 | uses: martinthomson/i-d-template@v1 40 | 41 | - name: "Upload to Datatracker" 42 | uses: martinthomson/i-d-template@v1 43 | with: 44 | make: upload 45 | 46 | - name: "Archive Submitted Drafts" 47 | uses: actions/upload-artifact@v4 48 | with: 49 | path: "draft-*-[0-9][0-9].xml" 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | /*-[0-9][0-9].xml 3 | *.html 4 | issues.json 5 | *.pdf 6 | pulls.json 7 | *.redxml 8 | .refcache 9 | report.xml 10 | *.swp 11 | .tags 12 | .targets.mk 13 | *.txt 14 | *.upload 15 | venv/ 16 | lib 17 | draft-marx-quic-logging-main-schema.xml 18 | .travis.yml 19 | *.cddl 20 | *.json 21 | *.lock -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | dist: xenial 4 | 5 | addons: 6 | apt: 7 | packages: 8 | - python-pip 9 | - xsltproc 10 | 11 | env: 12 | global: 13 | - GOPATH="${TRAVIS_BUILD_DIR}/.go_workspace" 14 | - mmark_src=github.com/miekg/mmark/mmark 15 | - mmark=./mmark 16 | 17 | install: 18 | - pip install xml2rfc 19 | - if head -1 -q *.md | grep '^\-\-\-' >/dev/null 2>&1; then gem install --no-doc kramdown-rfc2629; fi 20 | - if head -1 -q *.md | grep '^%%%' >/dev/null 2>&1; then go get "$mmark_src" && go build "$mmark_src"; fi 21 | 22 | script: 23 | - make 24 | - make issues || make issues DISABLE_ISSUE_FETCH=true && make gh-issues 25 | - make gh-pages 26 | 27 | deploy: 28 | provider: script 29 | script: make upload 30 | skip_cleanup: true 31 | on: 32 | tags: true 33 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This repository relates to activities in the Internet Engineering Task Force 4 | ([IETF](https://www.ietf.org/)). All material in this repository is considered 5 | Contributions to the IETF Standards Process, as defined in the intellectual 6 | property policies of IETF currently designated as 7 | [BCP 78](https://www.rfc-editor.org/info/bcp78), 8 | [BCP 79](https://www.rfc-editor.org/info/bcp79) and the 9 | [IETF Trust Legal Provisions (TLP) Relating to IETF Documents](http://trustee.ietf.org/trust-legal-provisions.html). 10 | 11 | Any edit, commit, pull request, issue, comment or other change made to this 12 | repository constitutes Contributions to the IETF Standards Process 13 | (https://www.ietf.org/). 14 | 15 | You agree to comply with all applicable IETF policies and procedures, including, 16 | BCP 78, 79, the TLP, and the TLP rules regarding code components (e.g. being 17 | subject to a Simplified BSD License) in Contributions. 18 | 19 | 20 | ## Other Resources 21 | 22 | Discussion of this work occurs on the 23 | [quic working group mailing list](https://mailarchive.ietf.org/arch/browse/quic/) 24 | ([subscribe](https://www.ietf.org/mailman/listinfo/quic)). In addition to 25 | contributions in GitHub, you are encouraged to participate in discussions there. 26 | 27 | **Note**: Some working groups adopt a policy whereby substantive discussion of 28 | technical issues needs to occur on the mailing list. 29 | 30 | You might also like to familiarize yourself with other 31 | [working group documents](https://datatracker.ietf.org/wg/quic/documents/). 32 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # something broke in the CDDL 0.12.1 update (github actions fails to install a native dependency somehow), 4 | # a fix was published by cddl for 0.12.4 so we need at least that (see https://github.com/martinthomson/i-d-template/issues/433#issuecomment-2173153568) 5 | gem 'cddl', '~> 0.12.4' -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | See the 4 | [guidelines for contributions](https://github.com/quicwg/qlog/blob/main/CONTRIBUTING.md). 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIBDIR := lib 2 | include $(LIBDIR)/main.mk 3 | 4 | $(LIBDIR)/main.mk: 5 | ifneq (,$(shell grep "path *= *$(LIBDIR)" .gitmodules 2>/dev/null)) 6 | git submodule sync 7 | git submodule update $(CLONE_ARGS) --init 8 | else 9 | git clone -q --depth 10 $(CLONE_ARGS) \ 10 | -b main https://github.com/martinthomson/i-d-template $(LIBDIR) 11 | endif 12 | 13 | cddl:: $(addsuffix .cddl,$(drafts)) 14 | 15 | # run cddl_validate.sh for all changed files 16 | %.cddl: %.md 17 | @for f in $@; do \ 18 | echo "Validating $$f"; \ 19 | ./cddl_validate.sh $$f > /tmp/foo-$$f 2>&1 ; \ 20 | if [ $$? -eq 0 ]; then \ 21 | echo " OK"; \ 22 | else \ 23 | echo " ERROR $$? : "; \ 24 | echo " debug with: ./cddl_validate.sh $$f"; \ 25 | fi; \ 26 | done 27 | 28 | # override lib/main.mk clean target, to cleanup json and cddl files 29 | .PHONY: clean 30 | clean:: 31 | $(MAKE) -f $(LIBDIR)/main.mk $@ 32 | -rm -f \ 33 | $(addsuffix -[0-9][0-9].{json$(COMMA)cddl},$(drafts)) \ 34 | $(addsuffix .{json$(COMMA)cddl},$(drafts)) 35 | 36 | # override lib/main.mk all target, to also install deps from Gemfile 37 | .PHONY: all 38 | all:: cddl 39 | $(MAKE) -f $(LIBDIR)/main.mk $@ 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qlog drafts 2 | 3 | This is the working area for IETF [QUIC Working Group](https://datatracker.ietf.org/wg/quic/documents/) Internet-Drafts concerning the qlog logging format for QUIC and HTTP/3. 4 | 5 | Three documents are currently defined: 6 | - The main schema: high-level schema, defining general logging format and principles 7 | - Event definitions for QUIC: concrete event definitions for the QUIC protocol 8 | - Event definitions for HTTP/3 and QPACK: concrete event definitions for the HTTP/3 and QPACK protocols 9 | 10 | ## Main logging schema for qlog 11 | 12 | * [Editor's Copy](https://quicwg.github.io/qlog/#go.draft-ietf-quic-qlog-main-schema.html) 13 | * [Working Group Draft](https://datatracker.ietf.org/doc/html/draft-ietf-quic-qlog-main-schema) 14 | * [Compare Editor's Copy to Working Group Draft](https://quicwg.github.io/qlog/#go.draft-ietf-quic-qlog-main-schema.diff) 15 | 16 | ## QUIC event definitions for qlog 17 | 18 | * [Editor's Copy](https://quicwg.github.io/qlog/#go.draft-ietf-quic-qlog-quic-events.html) 19 | * [Working Group Draft](https://datatracker.ietf.org/doc/html/draft-ietf-quic-qlog-quic-events) 20 | * [Compare Editor's Copy to Working Group Draft](https://quicwg.github.io/qlog/#go.draft-ietf-quic-qlog-quic-events.diff) 21 | 22 | ## HTTP/3 event definitions for qlog 23 | 24 | * [Editor's Copy](https://quicwg.github.io/qlog/#go.draft-ietf-quic-qlog-h3-events.html) 25 | * [Working Group Draft](https://datatracker.ietf.org/doc/html/draft-ietf-quic-qlog-h3-events) 26 | * [Compare Editor's Copy to Working Group Draft](https://quicwg.github.io/qlog/#go.draft-ietf-quic-qlog-h3-events.diff) 27 | 28 | 29 | ## Building the Draft 30 | 31 | Formatted text and HTML versions of the draft can be built using `make`. 32 | 33 | ```sh 34 | $ make 35 | ``` 36 | 37 | This requires that you have the necessary software installed. See 38 | [the instructions](https://github.com/martinthomson/i-d-template/blob/main/doc/SETUP.md). 39 | 40 | 41 | ## Contributing 42 | 43 | See the 44 | [guidelines for contributions](https://github.com/quicwg/qlog/blob/main/CONTRIBUTING.md). 45 | -------------------------------------------------------------------------------- /cddl_validate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # requires `gem install cddl` 4 | # 5 | set -e 6 | set -o nounset 7 | 8 | INPUT_FILE_ORIG="$1" 9 | BASE_FILENAME="${INPUT_FILE_ORIG%.*}" 10 | # so you can also pass the .cddl as argument, 11 | # which we seem to do due to recent makefile changes somehow... 12 | INPUT_FILE="${BASE_FILENAME}.md" 13 | CDDL_FILE="${BASE_FILENAME}.cddl" 14 | CDDL_JSON_FILE="${BASE_FILENAME}.json" 15 | 16 | :> $CDDL_FILE 17 | 18 | # Extracts CDDL from a markdown file 19 | # $1: the input (.md) file 20 | # $2: the output (.cddl) file 21 | function extract_cddl() { 22 | cat $1 | awk 'BEGIN{flag=0} /~~~ cddl/{flag=1; printf "\n"; next} /~~~/{flag=0; next} flag' >> $2 23 | } 24 | 25 | # Prepend an object with all the unused types to a CDDL file 26 | # This makes sure there is at least 1 instance of each type to be checked by the cddl tool 27 | # Additionally, this generates sample extensions for type and group sockets defined 28 | # This is especially useful for extension points that are defined, but not yet exercised in the current set of documents 29 | # $1: the input (.cddl) file name 30 | function generate_aux_object() { 31 | 32 | # There are two types of socket extensions: group and type sockets 33 | # - Group sockets are used to extend existing types with new fields 34 | # - Type sockets are used to make dynamic lists/ENUMs of types 35 | # We want to extract both so we can generate some random extension values for them 36 | # to make sure the extension points are usable by future documents 37 | 38 | # the group socket extensions look like this 39 | # * $$extension-name 40 | # nicely on their own row and everything :) so we extract rows that start like that, 41 | # and then discard the * with regex groups, since we won't need it. 42 | all_group_sockets=$(awk '/\* (\$\$.+)/ {print $2}' "$1") 43 | 44 | # the type sockets are a bit more involved, usually looking like this 45 | # $socket-name /= some-value / some-other-value 46 | # we need to extract just the first part (excluding the /=) 47 | all_type_sockets=$(awk '/.+ \/=/ {print $1}' "$1") 48 | 49 | # we need to remove the * from before the group sockets 50 | # in CDDL, the * indicates it's 0 or more 51 | # this is intentional, as most group sockets aren't used in the current documents, and so 0 is accurate 52 | # however, to force checking for correct use of the extension, we want the CDDL tool to act as if at least 1 is required 53 | # we get this by removing the *, so it is forced to look for an actual use of the extension point (which we generate later) 54 | original_cddl=`cat $1` 55 | orig="\* \$\$" 56 | target="\$\$" 57 | force_group_sockets_cddl="${original_cddl//${orig}/${target}}" # // replaces ALL occurrences 58 | echo "${force_group_sockets_cddl}" > $1 59 | 60 | # Generate the list of Unused types 61 | unused_types=$(cddl $1 generate 2>&1 | grep Unused | cut -d " " -f 4) 62 | 63 | # Create an object with all the unused types 64 | tmpfile=$(mktemp) 65 | echo "AuxObjectWithAllTypesForValidationOnly = {" >> $tmpfile 66 | for type in ${unused_types}; do 67 | lowercase_type=$(echo ${type} | tr '[:upper:]' '[:lower:]') 68 | # When using CDDL group sockets, they start with $$ 69 | # (see https://datatracker.ietf.org/doc/html/rfc8610#section-3.9) 70 | # These should not be included in the list of all objects here, 71 | # since this gives validation errors (e.g., $$my-socket-name is not a type) 72 | # Group sockets aren't types, and shouldn't be listed as such here 73 | if [[ $lowercase_type != \$\$* ]]; then 74 | echo " ${lowercase_type}_: ${type}" >> $tmpfile 75 | fi 76 | done 77 | echo -e "}\n" >> $tmpfile 78 | 79 | # generate sample extension data for the sockets 80 | for socket in ${all_group_sockets}; do 81 | # to test if the setup works, replace the next line with an empty echo; 82 | # you should see cddl errors :) 83 | echo " ${socket} //= ( new_field_name_test_$RANDOM: text )" >> $tmpfile 84 | done 85 | 86 | for socket in ${all_type_sockets}; do 87 | # to test if the setup works, search for "new_type_test" in the json output 88 | # it's a bit random (since the generator can also choose the "real" values if the type socket is being used) 89 | # but there should be some instances of this in there as well (esp. for ProtocolType in practice) 90 | echo " ${socket} /= \"new_type_test_$RANDOM\"" >> $tmpfile 91 | done 92 | 93 | tmpfile2=$(mktemp) 94 | cat $tmpfile $1 > $tmpfile2 95 | mv $tmpfile2 $1 96 | } 97 | 98 | if [ $INPUT_FILE != "draft-ietf-quic-qlog-main-schema.md" ]; then 99 | # Extracts CDDL from the main schema file 100 | extract_cddl draft-ietf-quic-qlog-main-schema.md $CDDL_FILE 101 | fi 102 | 103 | extract_cddl $INPUT_FILE $CDDL_FILE 104 | generate_aux_object $CDDL_FILE 105 | 106 | # The cddl command doesn't know how to work with .regexp with a give size. 107 | # We use that with hexstring sometimes, so clean that up 108 | tmpfile=$(mktemp) 109 | sed "s/hexstring .size .*/hexstring/" $CDDL_FILE > $tmpfile 110 | mv $tmpfile $CDDL_FILE 111 | 112 | # run the CDDL validator and generate the sample JSON file 113 | cddl ${CDDL_FILE} json-generate > ${CDDL_JSON_FILE} -------------------------------------------------------------------------------- /draft-ietf-quic-qlog-h3-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: HTTP/3 qlog event definitions 3 | docname: draft-ietf-quic-qlog-h3-events-latest 4 | category: std 5 | 6 | ipr: trust200902 7 | area: Transport 8 | workgroup: QUIC 9 | keyword: Internet-Draft 10 | 11 | stand_alone: yes 12 | pi: [toc, docindent, sortrefs, symrefs, strict, compact, comments, inline] 13 | 14 | author: 15 | - 16 | ins: R. Marx 17 | name: Robin Marx 18 | org: Akamai 19 | email: rmarx@akamai.com 20 | role: editor 21 | - 22 | ins: L. Niccolini 23 | name: Luca Niccolini 24 | org: Meta 25 | email: lniccolini@meta.com 26 | role: editor 27 | - 28 | ins: M. Seemann 29 | name: Marten Seemann 30 | email: martenseemann@gmail.com 31 | role: editor 32 | - ins: L. Pardue 33 | name: Lucas Pardue 34 | org: Cloudflare 35 | email: lucas@lucaspardue.com 36 | role: editor 37 | 38 | normative: 39 | RFC9110: 40 | display: HTTP 41 | 42 | RFC9114: 43 | display: HTTP/3 44 | 45 | QLOG-MAIN: 46 | I-D.ietf-quic-qlog-main-schema 47 | 48 | QLOG-QUIC: 49 | I-D.ietf-quic-qlog-quic-events 50 | 51 | informative: 52 | 53 | --- abstract 54 | 55 | This document defines a qlog event schema containing concrete events for the 56 | core HTTP/3 protocol and selected extensions. 57 | 58 | --- note_Note_to_Readers 59 | 60 | > Note to RFC editor: Please remove this section before publication. 61 | 62 | Feedback and discussion are welcome at 63 | [https://github.com/quicwg/qlog](https://github.com/quicwg/qlog). Readers are 64 | advised to refer to the "editor's draft" at that URL for an up-to-date version 65 | of this document. 66 | 67 | Concrete examples of integrations of this schema in 68 | various programming languages can be found at 69 | [https://github.com/quiclog/qlog/](https://github.com/quiclog/qlog/). 70 | 71 | --- middle 72 | 73 | # Introduction 74 | 75 | This document defines a qlog event schema ({{Section 8 of QLOG-MAIN}}) 76 | containing concrete events for the core HTTP/3 protocol {{RFC9114}} and selected 77 | extensions ({{!EXTENDED-CONNECT=RFC9220}}, {{!H3_PRIORITIZATION=RFC9218}}, and 78 | {{!H3-DATAGRAM=RFC9297}}). 79 | 80 | The event namespace with identifier `http3` is defined; see {{schema-def}}. In 81 | this namespace multiple events derive from the qlog abstract Event class 82 | ({{Section 7 of QLOG-MAIN}}), each extending the "data" field and defining 83 | their "name" field values and semantics. 84 | 85 | {{h3-events}} summarizes the name value of each event type that is defined in 86 | this specification. Some event data fields use complex data types. These are 87 | represented as enums or re-usable definitions, which are grouped together on the 88 | bottom of this document for clarity. 89 | 90 | | Name value | Importance | Definition | 91 | |:-----------------------------|:-----------|:------------| 92 | | http3:parameters_set | Base | {{h3-parametersset}} | 93 | | http3:parameters_restored | Base | {{h3-parametersrestored}} | 94 | | http3:stream_type_set | Base | {{h3-streamtypeset}} | 95 | | http3:priority_updated | Base | {{h3-priorityupdated}} | 96 | | http3:frame_created | Core | {{h3-framecreated}} | 97 | | http3:frame_parsed | Core | {{h3-frameparsed}} | 98 | | http3:datagram_created | Base | {{h3-datagramcreated}} | 99 | | http3:datagram_parsed | Base | {{h3-datagramparsed}} | 100 | | http3:push_resolved | Extra | {{h3-pushresolved}} | 101 | {: #h3-events title="HTTP/3 Events"} 102 | 103 | ## Usage with QUIC 104 | 105 | The events described in this document can be used with or without logging the 106 | related QUIC events defined in {{QLOG-QUIC}}. If used with QUIC events, the QUIC 107 | document takes precedence in terms of recommended filenames and trace separation 108 | setups. 109 | 110 | If used without QUIC events, it is recommended that the implementation assign a 111 | globally unique identifier to each HTTP/3 connection. This ID can then be used as 112 | the value of the qlog "group_id" field, as well as the qlog filename or file 113 | identifier, potentially suffixed by the vantagepoint type (For example, 114 | abcd1234_server.qlog would contain the server-side trace of the connection with 115 | GUID abcd1234). 116 | 117 | ## Notational Conventions 118 | 119 | {::boilerplate bcp14-tagged} 120 | 121 | The event and data structure definitions in ths document are expressed 122 | in the Concise Data Definition Language {{!CDDL=RFC8610}} and its 123 | extensions described in {{QLOG-MAIN}}. 124 | 125 | The following fields from {{QLOG-MAIN}} are imported and used: name, namespace, 126 | type, data, group_id, importance, RawInfo, and time-related fields. 127 | 128 | As is the case for {{QLOG-MAIN}}, the qlog schema definitions in this document 129 | are intentionally agnostic to serialization formats. The choice of format is an 130 | implementation decision. 131 | 132 | # Event Schema Definition {#schema-def} 133 | 134 | This document describes how the core HTTP/3 protocol and selected extensions can 135 | be expressed in qlog using a newly defined event schema. Per the requirements in 136 | {{Section 8 of QLOG-MAIN}}, this document registers the `http3` namespace. The 137 | event schema URI is `urn:ietf:params:qlog:events:http3`. 138 | 139 | ## Draft Event Schema Identification 140 | {:removeinrfc="true"} 141 | 142 | Only implementations of the final, published RFC can use the events belonging to 143 | the event schema with the URI `urn:ietf:params:qlog:events:http3`. Until such an 144 | RFC exists, implementations MUST NOT identify themselves using this URI. 145 | 146 | Implementations of draft versions of the event schema MUST append the string 147 | "-" and the corresponding draft number to the URI. For example, draft 07 of this 148 | document is identified using the URI `urn:ietf:params:qlog:events:http3-07`. 149 | 150 | The namespace identifier itself is not affected by this requirement. 151 | 152 | # HTTP/3 Events {#h3-ev} 153 | 154 | HTTP/3 events extend the `$ProtocolEventData` extension point defined in 155 | {{QLOG-MAIN}}. Additionally, they allow for direct extensibility by their use of 156 | per-event extension points via the `$$` CDDL "group socket" syntax, as also 157 | described in {{QLOG-MAIN}}. 158 | 159 | ~~~ cddl 160 | HTTP3EventData = HTTP3ParametersSet / 161 | HTTP3ParametersRestored / 162 | HTTP3StreamTypeSet / 163 | HTTP3PriorityUpdated / 164 | HTTP3FrameCreated / 165 | HTTP3FrameParsed / 166 | HTTP3DatagramCreated / 167 | HTTP3DatagramParsed / 168 | HTTP3PushResolved 169 | 170 | $ProtocolEventData /= HTTP3EventData 171 | ~~~ 172 | {: #h3-events-def title="HTTP3EventData definition and ProtocolEventData 173 | extension"} 174 | 175 | HTTP events are logged when a certain condition happens at the application 176 | layer, and there isn't always a one to one mapping between HTTP and QUIC events. 177 | The exchange of data between the HTTP and QUIC layer is logged via the 178 | "stream_data_moved" and "datagram_data_moved" events in {{QLOG-QUIC}}. 179 | 180 | HTTP/3 frames are transmitted on QUIC streams, which allows them to span 181 | multiple QUIC packets. Some implementations might send a single large frame, 182 | rather than a sequence of smaller frames, in order to amortize frame header 183 | overhead. HTTP/3 frame headers are represented by the frame_created 184 | ({{h3-framecreated}}) and frame_parsed ({{h3-frameparsed}}) events. Subsequent 185 | frame payload data transfer is indicated by stream_data_moved events. 186 | Furthermore, stream_data_moved events can appear before frame_parsed events 187 | because implementations need to read data from a stream in order to parse the 188 | frame header. 189 | 190 | The concrete HTTP/3 event types are further defined below, their type identifier 191 | is the heading name. 192 | 193 | ## parameters_set {#h3-parametersset} 194 | 195 | The `parameters_set` event contains HTTP/3 and QPACK-level settings, mostly 196 | those received from the HTTP/3 SETTINGS frame. It has Base importance level; see 197 | {{Section 9.2 of QLOG-MAIN}}. 198 | 199 | All these parameters are typically set once and never change. However, they 200 | might be set at different times during the connection, therefore a qlog can have 201 | multiple instances of `parameters_set` with different fields set. 202 | 203 | The "owner" field reflects how Settings are exchanged on a connection. Sent 204 | settings have the value "local" and received settings have the value 205 | "received". 206 | 207 | ~~~ cddl 208 | HTTP3ParametersSet = { 209 | ? owner: Owner 210 | 211 | ; RFC9114 212 | ? max_field_section_size: uint64 213 | 214 | ; RFC9204 215 | ? max_table_capacity: uint64 216 | ? blocked_streams_count: uint64 217 | 218 | ; RFC9220 (SETTINGS_ENABLE_CONNECT_PROTOCOL) 219 | ? extended_connect: uint16 220 | 221 | ; RFC9297 (SETTINGS_H3_DATAGRAM) 222 | ? h3_datagram: uint16 223 | 224 | ; qlog-specific 225 | ; indicates whether this implementation waits for a SETTINGS 226 | ; frame before processing requests 227 | ? waits_for_settings: bool 228 | 229 | * $$http3-parametersset-extension 230 | } 231 | ~~~ 232 | {: #h3-parametersset-def title="HTTP3ParametersSet definition"} 233 | 234 | The `parameters_set` event can contain any number of unspecified fields. This 235 | allows for representation of reserved settings (aka GREASE) or ad-hoc support 236 | for extension settings that do not have a related qlog schema definition. 237 | 238 | ## parameters_restored {#h3-parametersrestored} 239 | 240 | When using QUIC 0-RTT, HTTP/3 clients are expected to remember and reuse the 241 | server's SETTINGs from the previous connection. The `parameters_restored` event 242 | is used to indicate which HTTP/3 settings were restored and to which values when 243 | utilizing 0-RTT. It has Base importance level; see {{Section 9.2 of QLOG-MAIN}}. 244 | 245 | ~~~ cddl 246 | HTTP3ParametersRestored = { 247 | ; RFC9114 248 | ? max_field_section_size: uint64 249 | 250 | ; RFC9204 251 | ? max_table_capacity: uint64 252 | ? blocked_streams_count: uint64 253 | 254 | ; RFC9220 (SETTINGS_ENABLE_CONNECT_PROTOCOL) 255 | ? extended_connect: uint16 256 | 257 | ; RFC9297 (SETTINGS_H3_DATAGRAM) 258 | ? h3_datagram: uint16 259 | 260 | * $$http3-parametersrestored-extension 261 | } 262 | ~~~ 263 | {: #h3-parametersrestored-def title="HTTP3ParametersRestored definition"} 264 | 265 | ## stream_type_set {#h3-streamtypeset} 266 | 267 | The `stream_type_set` event conveys when a HTTP/3 stream type becomes known; see 268 | {{Sections 6.1 and 6.2 of RFC9114}}. It has Base importance level; see {{Section 269 | 9.2 of QLOG-MAIN}}. 270 | 271 | Client bidirectional streams always have a stream_type value of "request". 272 | Server bidirectional streams have no defined use, although extensions could 273 | change that. 274 | 275 | Unidirectional streams in either direction begin with with a variable-length 276 | integer type. Where the type is not known, the stream_type value of "unknown" 277 | type can be used and the value captured in the stream_type_bytes field; a 278 | numerical value without variable-length integer encoding. 279 | 280 | The generic `$HTTP3StreamType` is defined here as a CDDL "type socket" extension 281 | point. It can be extended to support additional HTTP/3 stream types. 282 | 283 | ~~~ cddl 284 | HTTP3StreamTypeSet = { 285 | ? owner: Owner 286 | stream_id: uint64 287 | stream_type: $HTTP3StreamType 288 | 289 | ; only when stream_type === "unknown" 290 | ? stream_type_bytes: uint64 291 | 292 | ; only when stream_type === "push" 293 | ? associated_push_id: uint64 294 | 295 | * $$http3-streamtypeset-extension 296 | } 297 | 298 | $HTTP3StreamType /= "request" / 299 | "control" / 300 | "push" / 301 | "reserved" / 302 | "unknown" / 303 | "qpack_encode" / 304 | "qpack_decode" 305 | ~~~ 306 | {: #h3-streamtypeset-def title="HTTP3StreamTypeSet definition"} 307 | 308 | ## priority_updated {#h3-priorityupdated} 309 | 310 | The `priority_updated` event is emitted when the priority of a request stream or 311 | push stream is initialized or updated through mechanisms defined in 312 | {{!RFC9218}}. It has Base importance level; see {{Section 9.2 of QLOG-MAIN}}. 313 | 314 | There can be several reasons why a `priority_updated` occurs, and why a 315 | particular value was chosen. For example, the priority can be updated through 316 | signals received from client and/or server (e.g., in HTTP/3 HEADERS or 317 | PRIORITY_UPDATE frames) or it can be changed or overridden due to local 318 | policies. The `trigger` and `reason` fields can be used to optionally 319 | capture such details. 320 | 321 | ~~~ cddl 322 | HTTP3PriorityUpdated = { 323 | ; if the prioritized element is a request stream 324 | ? stream_id: uint64 325 | 326 | ; if the prioritized element is a push stream 327 | ? push_id: uint64 328 | 329 | ? old: HTTP3Priority 330 | new: HTTP3Priority 331 | 332 | ? trigger: "client_signal_received" / 333 | "local" / 334 | "other" 335 | 336 | ? reason: "client_signal_only" / 337 | "client_server_merged" / 338 | "local_policy" / 339 | "other" 340 | 341 | * $$http3-priorityupdated-extension 342 | } 343 | ~~~ 344 | {: #h3-priorityupdated-def title="HTTP3PriorityUpdated definition"} 345 | 346 | ## frame_created {#h3-framecreated} 347 | 348 | The `frame_created` event is emitted when the HTTP/3 framing actually happens. 349 | It has Core importance level; see {{Section 9.2 of QLOG-MAIN}}. 350 | 351 | This event does not necessarily coincide with HTTP/3 data getting passed to the 352 | QUIC layer. For that, see the `stream_data_moved` event in {{QLOG-QUIC}}. 353 | 354 | ~~~ cddl 355 | HTTP3FrameCreated = { 356 | stream_id: uint64 357 | ? length: uint64 358 | frame: $HTTP3Frame 359 | ? raw: RawInfo 360 | 361 | * $$http3-framecreated-extension 362 | } 363 | ~~~ 364 | {: #h3-framecreated-def title="HTTP3FrameCreated definition"} 365 | 366 | ## frame_parsed {#h3-frameparsed} 367 | 368 | The `frame_parsed` event is emitted when the HTTP/3 frame is parsed. It has Core 369 | importance level; see {{Section 9.2 of QLOG-MAIN}}. 370 | 371 | This event is not necessarily the same as when the HTTP/3 data is actually 372 | received on the QUIC layer. For that, see the `stream_data_moved` event in 373 | {{QLOG-QUIC}}. 374 | 375 | ~~~ cddl 376 | HTTP3FrameParsed = { 377 | stream_id: uint64 378 | ? length: uint64 379 | frame: $HTTP3Frame 380 | ? raw: RawInfo 381 | 382 | * $$h3-frameparsed-extension 383 | } 384 | ~~~ 385 | {: #h3-frameparsed-def title="HTTP3FrameParsed definition"} 386 | 387 | 388 | ## datagram_created {#h3-datagramcreated} 389 | 390 | The `datagram_created` event is emitted when an HTTP/3 Datagram is created (see 391 | {{!RFC9297}}). It has Base importance level; see {{Section 9.2 of QLOG-MAIN}}. 392 | 393 | This event does not necessarily coincide with the HTTP/3 Datagram getting passed 394 | to the QUIC layer. For that, see the `datagram_data_moved` event in 395 | {{QLOG-QUIC}}. 396 | 397 | ~~~ cddl 398 | HTTP3DatagramCreated = { 399 | quarter_stream_id: uint64 400 | ? datagram: $HTTP3Datagram 401 | ? raw: RawInfo 402 | 403 | * $$http3-datagramcreated-extension 404 | } 405 | ~~~ 406 | {: #h3-datagramcreated-def title="HTTP3DatagramCreated definition"} 407 | 408 | ## datagram_parsed {#h3-datagramparsed} 409 | 410 | The `datagram_parsed` event is emitted when the HTTP/3 Datagram is parsed (see 411 | {{!RFC9297}}). It has Base importance level; see {{Section 9.2 of QLOG-MAIN}}. 412 | 413 | This event is not necessarily the same as when the HTTP/3 Datagram is actually 414 | received on the QUIC layer. For that, see the `datagram_data_moved` event in 415 | {{QLOG-QUIC}}. 416 | 417 | ~~~ cddl 418 | HTTP3DatagramParsed = { 419 | quarter_stream_id: uint64 420 | ? datagram: $HTTP3Datagram 421 | ? raw: RawInfo 422 | 423 | * $$http3-datagramparsed-extension 424 | } 425 | ~~~ 426 | {: #h3-datagramparsed-def title="HTTP3DatagramParsed definition"} 427 | 428 | ## push_resolved {#h3-pushresolved} 429 | 430 | The `push_resolved` event is emitted when a pushed resource ({{Section 4.6 of 431 | RFC9114}}) is successfully claimed (used) or, conversely, abandoned (rejected) 432 | by the application on top of HTTP/3 (e.g., the web browser). This event provides 433 | additional context that can is aid debugging issues related to server push. It 434 | has Extra importance level; see {{Section 9.2 of QLOG-MAIN}}. 435 | 436 | ~~~ cddl 437 | HTTP3PushResolved = { 438 | ? push_id: uint64 439 | 440 | ; in case this is logged from a place that does not have access 441 | ; to the push_id 442 | ? stream_id: uint64 443 | decision: HTTP3PushDecision 444 | 445 | * $$http3-pushresolved-extension 446 | } 447 | 448 | HTTP3PushDecision = "claimed" / 449 | "abandoned" 450 | ~~~ 451 | {: #h3-pushresolved-def title="HTTP3PushResolved definition"} 452 | 453 | # HTTP/3 Data Type Definitions 454 | 455 | The following data type definitions can be used in HTTP/3 events. 456 | 457 | ## Owner 458 | 459 | ~~~ cddl 460 | Owner = "local" / 461 | "remote" 462 | ~~~ 463 | {: #owner-def title="Owner definition"} 464 | 465 | ## HTTP3Frame 466 | 467 | The generic `$HTTP3Frame` is defined here as a CDDL "type socket" extension point. 468 | It can be extended to support additional HTTP/3 frame types. 469 | 470 | ~~~~~~ 471 | ; The HTTP3Frame is any key-value map (e.g., JSON object) 472 | $HTTP3Frame /= { 473 | * text => any 474 | } 475 | ~~~~~~ 476 | {: #h3-frame-def title="HTTP3Frame type socket definition"} 477 | 478 | The HTTP/3 frame types defined in this document are as follows: 479 | 480 | ~~~ cddl 481 | HTTP3BaseFrames = HTTP3DataFrame / 482 | HTTP3HeadersFrame / 483 | HTTP3CancelPushFrame / 484 | HTTP3SettingsFrame / 485 | HTTP3PushPromiseFrame / 486 | HTTP3GoawayFrame / 487 | HTTP3MaxPushIDFrame / 488 | HTTP3ReservedFrame / 489 | HTTP3UnknownFrame 490 | 491 | $HTTP3Frame /= HTTP3BaseFrames 492 | ~~~ 493 | {: #h3baseframe-def title="HTTP3BaseFrames definition"} 494 | 495 | ## HTTP3Datagram 496 | 497 | The generic `$HTTP3Datagram` is defined here as a CDDL "type socket" extension 498 | point. It can be extended to support additional HTTP/3 datagram types. This 499 | document intentionally does not define any specific qlog schemas for specific 500 | HTTP/3 Datagram types. 501 | 502 | ~~~~~~ 503 | ; The HTTP3Datagram is any key-value map (e.g., JSON object) 504 | $HTTP3Datagram /= { 505 | * text => any 506 | } 507 | ~~~~~~ 508 | {: #h3-datagram-def title="HTTP3Datagram type socket definition"} 509 | 510 | ### HTTP3DataFrame 511 | 512 | ~~~ cddl 513 | HTTP3DataFrame = { 514 | frame_type: "data" 515 | ? raw: RawInfo 516 | } 517 | ~~~ 518 | {: #h3dataframe-def title="HTTP3DataFrame definition"} 519 | 520 | ### HTTP3HeadersFrame 521 | 522 | The payload of an HTTP/3 HEADERS frame is the QPACK-encoding of an HTTP field 523 | section; see {{Section 7.2.2 of RFC9114}}. `HTTP3HeaderFrame`, in contrast, 524 | contains the HTTP field section without QPACK encoding. 525 | 526 | ~~~ cddl 527 | HTTP3HTTPField = { 528 | ? name: text 529 | ? name_bytes: hexstring 530 | ? value: text 531 | ? value_bytes: hexstring 532 | } 533 | ~~~ 534 | {: #h3field-def title="HTTP3HTTPField definition"} 535 | 536 | ~~~ cddl 537 | HTTP3HeadersFrame = { 538 | frame_type: "headers" 539 | headers: [* HTTP3HTTPField] 540 | ? raw: RawInfo 541 | } 542 | ~~~ 543 | {: #h3-headersframe-def title="HTTP3HeadersFrame definition"} 544 | 545 | For example, the HTTP field section 546 | 547 | ~~~ 548 | :path: /index.html 549 | :method: GET 550 | :authority: example.org 551 | :scheme: https 552 | ~~~ 553 | 554 | would be represented in a JSON serialization as: 555 | 556 | ~~~ 557 | headers: [ 558 | { 559 | "name": ":path", 560 | "value": "/" 561 | }, 562 | { 563 | "name": ":method", 564 | "value": "GET" 565 | }, 566 | { 567 | "name": ":authority", 568 | "value": "example.org" 569 | }, 570 | { 571 | "name": ":scheme", 572 | "value": "https" 573 | } 574 | ] 575 | ~~~ 576 | {: #h3-headersframe-ex title="HTTP3HeadersFrame example"} 577 | 578 | {{Section 4.2 of RFC9114}} and {{Section 5.1 of RFC9110}} define rules for the 579 | characters used in HTTP field sections names and values. Characters outside the 580 | range are invalid and result in the message being treated as malformed. It can 581 | however be useful to also log these invalid HTTP fields. Characters in the 582 | allowed range can be safely logged by the text type used in the `name` and 583 | `value` fields of `HTTP3HTTPField`. Characters outside the range are unsafe for the 584 | text type and need to be logged using the `name_bytes` and `value_bytes` field. 585 | An instance of `HTTP3HTTPField` MUST include either the `name` or `name_bytes` 586 | field and MAY include both. An `HTTP3HTTPField` MAY include a `value` or 587 | `value_bytes` field or neither. 588 | 589 | ### HTTP3CancelPushFrame 590 | 591 | ~~~ cddl 592 | HTTP3CancelPushFrame = { 593 | frame_type: "cancel_push" 594 | push_id: uint64 595 | ? raw: RawInfo 596 | } 597 | ~~~ 598 | {: #h3-cancelpushframe-def title="HTTP3CancelPushFrame definition"} 599 | 600 | ### HTTP3SettingsFrame 601 | 602 | The settings field can contain zero or more entries. Each setting has a name 603 | field, which corresponds to Setting Name as defined (or as would be defined if 604 | registered) in the "HTTP/3 Settings" registry maintained at 605 | . 606 | 607 | An endpoint that receives unknown settings is not able to log a specific name. 608 | Instead, the name value of "unknown" can be used and the value captured in the 609 | `name_bytes` field; a numerical value without variable-length integer encoding. 610 | 611 | ~~~ cddl 612 | HTTP3SettingsFrame = { 613 | frame_type: "settings" 614 | settings: [* HTTP3Setting] 615 | ? raw: RawInfo 616 | } 617 | 618 | HTTP3Setting = { 619 | ? name: $HTTP3SettingsName 620 | ; only when name === "unknown" 621 | ? name_bytes: uint64 622 | 623 | value: uint64 624 | } 625 | 626 | $HTTP3SettingsName /= "settings_qpack_max_table_capacity" / 627 | "settings_max_field_section_size" / 628 | "settings_qpack_blocked_streams" / 629 | "settings_enable_connect_protocol" / 630 | "settings_h3_datagram" / 631 | "reserved" / 632 | "unknown" 633 | ~~~ 634 | {: #h3settingsframe-def title="HTTP3SettingsFrame definition"} 635 | 636 | ### HTTP3PushPromiseFrame 637 | 638 | ~~~ cddl 639 | HTTP3PushPromiseFrame = { 640 | frame_type: "push_promise" 641 | push_id: uint64 642 | headers: [* HTTP3HTTPField] 643 | ? raw: RawInfo 644 | } 645 | ~~~ 646 | {: #h3pushpromiseframe-def title="HTTP3PushPromiseFrame definition"} 647 | 648 | ### HTTP3GoAwayFrame 649 | 650 | ~~~ cddl 651 | HTTP3GoawayFrame = { 652 | frame_type: "goaway" 653 | 654 | ; Either stream_id or push_id. 655 | ; This is implicit from the sender of the frame 656 | id: uint64 657 | ? raw: RawInfo 658 | } 659 | ~~~ 660 | {: #h3goawayframe-def title="HTTP3GoawayFrame definition"} 661 | 662 | ### HTTP3MaxPushIDFrame 663 | 664 | ~~~ cddl 665 | HTTP3MaxPushIDFrame = { 666 | frame_type: "max_push_id" 667 | push_id: uint64 668 | ? raw: RawInfo 669 | } 670 | ~~~ 671 | {: #h3maxpushidframe-def title="HTTP3MaxPushIDFrame definition"} 672 | 673 | ### HTTP3PriorityUpdateFrame 674 | 675 | The PRIORITY_UPDATE frame is defined in {{!RFC9218}}. 676 | 677 | ~~~ cddl 678 | HTTP3PriorityUpdateFrame = { 679 | frame_type: "priority_update" 680 | 681 | ; if the prioritized element is a request stream 682 | ? stream_id: uint64 683 | 684 | ; if the prioritized element is a push stream 685 | ? push_id: uint64 686 | 687 | priority_field_value: HTTP3Priority 688 | ? raw: RawInfo 689 | } 690 | 691 | ; The priority value in ASCII text, encoded using Structured Fields 692 | ; Example: u=5, i 693 | HTTP3Priority = text 694 | ~~~ 695 | {: #h3priorityupdateframe-def title="HTTP3PriorityUpdateFrame definition"} 696 | 697 | ### HTTP3ReservedFrame 698 | 699 | The frame_type_bytes field is the numerical value without variable-length 700 | integer encoding. 701 | 702 | ~~~ cddl 703 | HTTP3ReservedFrame = { 704 | frame_type: "reserved" 705 | frame_type_bytes: uint64 706 | ? raw: RawInfo 707 | } 708 | ~~~ 709 | {: #h3reservedframe-def title="HTTP3ReservedFrame definition"} 710 | 711 | ### HTTP3UnknownFrame 712 | 713 | The frame_type_bytes field is the numerical value without variable-length 714 | integer encoding. 715 | 716 | ~~~ cddl 717 | HTTP3UnknownFrame = { 718 | frame_type: "unknown" 719 | frame_type_bytes: uint64 720 | ? raw: RawInfo 721 | } 722 | ~~~ 723 | {: #h3unknownframe-def title="HTTP3UnknownFrame definition"} 724 | 725 | ### HTTP3ApplicationError 726 | 727 | ~~~ cddl 728 | HTTP3ApplicationError = "http_no_error" / 729 | "http_general_protocol_error" / 730 | "http_internal_error" / 731 | "http_stream_creation_error" / 732 | "http_closed_critical_stream" / 733 | "http_frame_unexpected" / 734 | "http_frame_error" / 735 | "http_excessive_load" / 736 | "http_id_error" / 737 | "http_settings_error" / 738 | "http_missing_settings" / 739 | "http_request_rejected" / 740 | "http_request_cancelled" / 741 | "http_request_incomplete" / 742 | "http_early_response" / 743 | "http_connect_error" / 744 | "http_version_fallback" 745 | ~~~ 746 | {: #h3-applicationerror-def title="HTTP3ApplicationError definition"} 747 | 748 | The HTTP3ApplicationError extends the general $ApplicationError 749 | definition in the qlog QUIC document, see {{QLOG-QUIC}}. 750 | 751 | ~~~ cddl 752 | ; ensure HTTP errors are properly validated in QUIC events as well 753 | ; e.g., QUIC's ConnectionClose Frame 754 | $ApplicationError /= HTTP3ApplicationError 755 | ~~~ 756 | 757 | # Security and Privacy Considerations 758 | 759 | The security and privacy considerations discussed in {{QLOG-MAIN}} apply to this 760 | document as well. 761 | 762 | # IANA Considerations 763 | 764 | This document registers a new entry in the "qlog event schema URIs" registry. 765 | 766 | Event schema URI: 767 | : urn:ietf:params:qlog:events:http3 768 | 769 | Namespace 770 | : http3 771 | 772 | Event Types 773 | : parameters_set,parameters_restored,stream_type_set,priority_updated,frame_created,frame_parsed,datagram_created,datagram_parsed,push_resolved 774 | 775 | Description: 776 | : Event definitions related to the HTTP/3 application protocol. 777 | 778 | Reference: 779 | : This Document 780 | 781 | --- back 782 | 783 | # Acknowledgements 784 | {:numbered="false"} 785 | 786 | Much of the initial work by Robin Marx was done at the Hasselt and KU Leuven 787 | Universities. 788 | 789 | Thanks to Jana Iyengar, Brian Trammell, Dmitri Tikhonov, Stephen Petrides, Jari 790 | Arkko, Marcus Ihlar, Victor Vasiliev, Mirja Kühlewind, Jeremy Lainé, Kazu 791 | Yamamoto, Christian Huitema, Hugo Landau and Jonathan Lennox for their feedback 792 | and suggestions. 793 | 794 | # Change Log 795 | {:numbered="false" removeinrfc="true"} 796 | 797 | ## Since draft-ietf-quic-qlog-h3-events-09: 798 | {:numbered="false"} 799 | 800 | * Several editorial changes 801 | * Consistent use of RawInfo and _bytes fields to log raw data (#450) 802 | 803 | ## Since draft-ietf-quic-qlog-h3-events-08: 804 | {:numbered="false"} 805 | 806 | * Removed individual categories and put every event in the single `http3` event 807 | schema namespace. Major change (#439) 808 | * Changed protocol id from `HTTP3` to `HTTP/3` (#428) 809 | 810 | ## Since draft-ietf-quic-qlog-h3-events-07: 811 | {:numbered="false"} 812 | 813 | * TODO (we forgot...) 814 | 815 | ## Since draft-ietf-quic-qlog-h3-events-06: 816 | {:numbered="false"} 817 | 818 | * ProtocolEventBody is now called ProtocolEventData (#352) 819 | * Editorial changes (#402) 820 | 821 | ## Since draft-ietf-quic-qlog-h3-events-05: 822 | {:numbered="false"} 823 | 824 | * Removed all qpack event definitions (#335) 825 | * Various editorial changes 826 | 827 | ## Since draft-ietf-quic-qlog-h3-events-04: 828 | {:numbered="false"} 829 | 830 | * Renamed 'http' category to 'h3' (#300) 831 | * H3HTTPField.value is now optional (#296) 832 | * Added definitions for RFC9297 (HTTP/3 Datagram extension) (#310) 833 | * Added definitions for RFC9218 (HTTP Extensible Prioritizations extension) (#312) 834 | * Added definitions for RFC9220 (Extended Connect extension) (#325) 835 | * Editorial and formatting changes (#298, #258, #299, #304, #327) 836 | 837 | ## Since draft-ietf-quic-qlog-h3-events-03: 838 | {:numbered="false"} 839 | 840 | * Ensured consistent use of RawInfo to indicate raw wire bytes (#243) 841 | * Changed HTTPStreamTypeSet:raw_stream_type to stream_type_value (#54) 842 | * Changed HTTPUnknownFrame:raw_frame_type to frame_type_value (#54) 843 | * Renamed max_header_list_size to max_field_section_size (#282) 844 | 845 | ## Since draft-ietf-quic-qlog-h3-events-02: 846 | {:numbered="false"} 847 | 848 | * Renamed HTTPStreamType data to request (#222) 849 | * Added HTTPStreamType value unknown (#227) 850 | * Added HTTPUnknownFrame (#224) 851 | * Replaced old and new fields with stream_type in HTTPStreamTypeSet (#240) 852 | * Changed HTTPFrame to a CDDL plug type (#257) 853 | * Moved data definitions out of the appendix into separate sections 854 | * Added overview Table of Contents 855 | 856 | ## Since draft-ietf-quic-qlog-h3-events-01: 857 | {:numbered="false"} 858 | 859 | * No changes - new draft to prevent expiration 860 | 861 | ## Since draft-ietf-quic-qlog-h3-events-00: 862 | {:numbered="false"} 863 | 864 | * Change the data definition language from TypeScript to CDDL (#143) 865 | 866 | ## Since draft-marx-qlog-event-definitions-quic-h3-02: 867 | {:numbered="false"} 868 | 869 | * These changes were done in preparation of the adoption of the drafts by the QUIC 870 | working group (#137) 871 | * Split QUIC and HTTP/3 events into two separate documents 872 | * Moved RawInfo, Importance, Generic events and Simulation events to the main 873 | schema document. 874 | 875 | ## Since draft-marx-qlog-event-definitions-quic-h3-01: 876 | {:numbered="false"} 877 | 878 | Major changes: 879 | 880 | * Moved data_moved from http to transport. Also made the "from" and "to" fields 881 | flexible strings instead of an enum (#111,#65) 882 | * Moved packet_type fields to PacketHeader. Moved packet_size field out of 883 | PacketHeader to RawInfo:length (#40) 884 | * Made events that need to log packet_type and packet_number use a header field 885 | instead of logging these fields individually 886 | * Added support for logging retry, stateless reset and initial tokens (#94,#86,#117) 887 | * Moved separate general event categories into a single category "generic" (#47) 888 | * Added "transport:connection_closed" event (#43,#85,#78,#49) 889 | * Added version_information and alpn_information events (#85,#75,#28) 890 | * Added parameters_restored events to help clarify 0-RTT behaviour (#88) 891 | 892 | Smaller changes: 893 | 894 | * Merged loss_timer events into one loss_timer_updated event 895 | * Field data types are now strongly defined (#10,#39,#36,#115) 896 | * Renamed qpack instruction_received and instruction_sent to instruction_created 897 | and instruction_parsed (#114) 898 | * Updated qpack:dynamic_table_updated.update_type. It now has the value "inserted" 899 | instead of "added" (#113) 900 | * Updated qpack:dynamic_table_updated. It now has an "owner" field to 901 | differentiate encoder vs decoder state (#112) 902 | * Removed push_allowed from http:parameters_set (#110) 903 | * Removed explicit trigger field indications from events, since this was moved to 904 | be a generic property of the "data" field (#80) 905 | * Updated transport:connection_id_updated to be more in line with other similar 906 | events. Also dropped importance from Core to Base (#45) 907 | * Added length property to PaddingFrame (#34) 908 | * Added packet_number field to transport:frames_processed (#74) 909 | * Added a way to generically log packet header flags (first 8 bits) to 910 | PacketHeader 911 | * Added additional guidance on which events to log in which situations (#53) 912 | * Added "simulation:scenario" event to help indicate simulation details 913 | * Added "packets_acked" event (#107) 914 | * Added "datagram_ids" to the datagram_X and packet_X events to allow tracking of 915 | coalesced QUIC packets (#91) 916 | * Extended connection_state_updated with more fine-grained states (#49) 917 | 918 | ## Since draft-marx-qlog-event-definitions-quic-h3-00: 919 | {:numbered="false"} 920 | 921 | * Event and category names are now all lowercase 922 | * Added many new events and their definitions 923 | * "type" fields have been made more specific (especially important for PacketType 924 | fields, which are now called packet_type instead of type) 925 | * Events are given an importance indicator (issue \#22) 926 | * Event names are more consistent and use past tense (issue \#21) 927 | * Triggers have been redefined as properties of the "data" field and updated for most events (issue \#23) 928 | -------------------------------------------------------------------------------- /draft-ietf-quic-qlog-main-schema.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "qlog: Structured Logging for Network Protocols" 3 | abbrev: qlog 4 | docname: draft-ietf-quic-qlog-main-schema-latest 5 | category: std 6 | 7 | ipr: trust200902 8 | area: Transport 9 | workgroup: QUIC 10 | keyword: Internet-Draft 11 | 12 | stand_alone: yes 13 | pi: [toc, docindent, sortrefs, symrefs, strict, compact, comments, inline] 14 | 15 | author: 16 | - 17 | ins: R. Marx 18 | name: Robin Marx 19 | org: Akamai 20 | email: rmarx@akamai.com 21 | role: editor 22 | - 23 | ins: L. Niccolini 24 | name: Luca Niccolini 25 | org: Meta 26 | email: lniccolini@meta.com 27 | role: editor 28 | - 29 | ins: M. Seemann 30 | name: Marten Seemann 31 | email: martenseemann@gmail.com 32 | role: editor 33 | - ins: L. Pardue 34 | name: Lucas Pardue 35 | org: Cloudflare 36 | email: lucas@lucaspardue.com 37 | role: editor 38 | 39 | normative: 40 | 41 | informative: 42 | QLOG-QUIC: 43 | I-D.ietf-quic-qlog-quic-events 44 | 45 | QLOG-H3: 46 | I-D.ietf-quic-qlog-h3-events 47 | 48 | ANRW-2020: 49 | target: https://qlog.edm.uhasselt.be/anrw/ 50 | title: "Debugging QUIC and HTTP/3 with qlog and qvis" 51 | date: 2020-09 52 | author: 53 | - 54 | name: Robin Marx 55 | - 56 | name: Maxime Piraux 57 | - 58 | name: Peter Quax 59 | - 60 | name: Wim Lamotte 61 | 62 | 63 | --- abstract 64 | 65 | qlog provides extensible structured logging for network protocols, allowing for 66 | easy sharing of data that benefits common debug and analysis methods and 67 | tooling. This document describes key concepts of qlog: formats, files, traces, 68 | events, and extension points. This definition includes the high-level log file 69 | schemas, and generic event schemas. Requirements and guidelines for creating 70 | protocol-specific event schemas are also presented. All schemas are defined 71 | independent of serialization format, allowing logs to be represented in various 72 | ways such as JSON, CSV, or protobuf. 73 | 74 | --- note_Note_to_Readers 75 | 76 | > Note to RFC editor: Please remove this section before publication. 77 | 78 | Feedback and discussion are welcome at 79 | [https://github.com/quicwg/qlog](https://github.com/quicwg/qlog). Readers are 80 | advised to refer to the "editor's draft" at that URL for an up-to-date version 81 | of this document. 82 | 83 | Concrete examples of integrations of this schema in 84 | various programming languages can be found at 85 | [https://github.com/quiclog/qlog/](https://github.com/quiclog/qlog/). 86 | 87 | --- middle 88 | 89 | # Introduction 90 | 91 | Endpoint logging is a useful strategy for capturing and understanding how 92 | applications using network protocols are behaving, particularly where protocols 93 | have an encrypted wire image that restricts observers' ability to see what is 94 | happening. 95 | 96 | Many applications implement logging using a custom, non-standard logging format. 97 | This has an effect on the tools and methods that are used to 98 | analyze the logs, for example to perform root cause analysis of an 99 | interoperability failure between distinct implementations. A lack of a common 100 | format impedes the development of common tooling that can be used by all parties 101 | that have access to logs. 102 | 103 | qlog is an extensible structured logging for network protocols that allows for 104 | easy sharing of data that benefits common debug and analysis methods and 105 | tooling. This document describes key concepts of qlog: formats, files, traces, 106 | events, and extension points. This definition includes the high-level log file 107 | schemas, and generic event schemas. Requirements and guidelines for creating 108 | protocol-specific event schemas are also presented. Accompanying documents 109 | define event schemas for QUIC ({{QLOG-QUIC}}) and HTTP/3 ({{QLOG-H3}}). 110 | 111 | The goal of qlog is to provide amenities and default characteristics that each 112 | logging file should contain (or should be able to contain), such that generic 113 | and reusable toolsets can be created that can deal with logs from a variety of 114 | different protocols and use cases. 115 | 116 | As such, qlog provides versioning, metadata inclusion, log aggregation, event 117 | grouping and log file size reduction techniques. 118 | 119 | All qlog schemas can be serialized in many ways (e.g., JSON, CBOR, protobuf, 120 | etc). This document describes only how to employ {{!JSON=RFC8259}}, its subset 121 | {{!I-JSON=RFC7493}}, and its streamable derivative 122 | {{!JSON-Text-Sequences=RFC7464}}. 123 | 124 | 125 | ## Conventions and Terminology 126 | 127 | {::boilerplate bcp14-tagged} 128 | 129 | Serialization examples in this document use JSON ({{!JSON=RFC8259}}) unless 130 | otherwise indicated. 131 | 132 | ## Use of CDDL 133 | 134 | To define events and data structures, all qlog documents use the Concise Data 135 | Definition Language {{!CDDL=RFC8610}}. This document uses the basic syntax, the 136 | specific `text`, `uint`, `float32`, `float64`, `bool`, and `any` types, as well 137 | as the `.default`, `.size`, and `.regexp` control operators, the `~` unwrapping 138 | operator, and the `$` and `$$` extension points syntax from {{CDDL}}. 139 | 140 | Additionally, this document defines the following custom types for 141 | clarity: 142 | 143 | ~~~ cddl 144 | ; CDDL's uint is defined as being 64-bit in size 145 | ; but for many protocol fields it is better to be restrictive 146 | ; and explicit 147 | uint8 = uint .size 1 148 | uint16 = uint .size 2 149 | uint32 = uint .size 4 150 | uint64 = uint .size 8 151 | 152 | ; an even-length lowercase string of hexadecimally encoded bytes 153 | ; examples: 82dc, 027339, 4cdbfd9bf0 154 | ; this is needed because the default CDDL binary string (bytes/bstr) 155 | ; is only CBOR and not JSON compatible 156 | hexstring = text .regexp "([0-9a-f]{2})*" 157 | ~~~ 158 | {: #cddl-custom-types-def title="Additional CDDL type definitions"} 159 | 160 | All timestamps and time-related values (e.g., offsets) in qlog are 161 | logged as `float64` in the millisecond resolution. 162 | 163 | Other qlog documents can define their own CDDL-compatible (struct) types 164 | (e.g., separately for each Packet type that a protocol supports). 165 | 166 | The ordering of member fields in qlog CDDL type definitions is not significant. 167 | The ordering of member fields in the serialization formats defined in this 168 | document, JSON ({{format-json}}) and JSON Text Sequences ({{format-json-seq}}), 169 | is not significant and qlog tools MUST NOT assume so. Other qlog serialization 170 | formats MAY define field order significance, if they do they MUST define 171 | requirements for qlog tools supporting those formats. 172 | 173 | > Note to RFC editor: Please remove the following text in this section before 174 | publication. 175 | 176 | The main general CDDL syntax conventions in this document a reader 177 | should be aware of for easy reading comprehension are: 178 | 179 | * `? obj` : this object is optional 180 | * `TypeName1 / TypeName2` : a union of these two types (object can be either type 1 OR 181 | type 2) 182 | * `obj: TypeName` : this object has this concrete type 183 | * `obj: [* TypeName]` : this object is an array of this type with 184 | minimum size of 0 elements 185 | * `obj: [+ TypeName]` : this object is an array of this type with 186 | minimum size of 1 element 187 | * `TypeName = ...` : defines a new type 188 | * `EnumName = "entry1" / "entry2" / entry3 / ...`: defines an enum 189 | * `StructName = { ... }` : defines a new struct type 190 | * `;` : single-line comment 191 | * `* text => any` : special syntax to indicate 0 or more fields that 192 | have a string key that maps to any value. Used to indicate a generic 193 | JSON object. 194 | 195 | All timestamps and time-related values (e.g., offsets) in qlog are 196 | logged as `float64` in the millisecond resolution. 197 | 198 | Other qlog documents can define their own CDDL-compatible (struct) types 199 | (e.g., separately for each Packet type that a protocol supports). 200 | 201 | # Design Overview 202 | 203 | The main tenets for the qlog design are: 204 | 205 | * Streamable, event-based logging 206 | * A flexible format that can reduce log producer overhead, at the cost of 207 | increased complexity for consumers (e.g. tools) 208 | * Extensible and pragmatic 209 | * Aggregation and transformation friendly (e.g., the top-level element 210 | for the non-streaming format is a container for individual traces, 211 | group_ids can be used to tag events to a particular context) 212 | * Metadata is stored together with event data 213 | 214 | This is achieved by a logical logging hierarchy of: 215 | 216 | * Log file 217 | * Trace(s) 218 | * Event(s) 219 | 220 | An abstract LogFile class is declared ({{abstract-logfile}}), from which all 221 | concrete log file formats derive using log file schemas. This document defines 222 | the QLogFile ({{qlog-file-schema}}) and QLogFileSeq ({{qlog-file-seq-schema}}) 223 | log file schemas. 224 | 225 | A trace is conceptually fluid but the conventional use case is to group events 226 | related to a single data flow, such as a single logical QUIC connection, at a 227 | single vantage point ({{vantage-point}}). Concrete trace definitions relate to 228 | the log file schemas they are contained in; see ({{traces}}, {{trace}}, and 229 | {{traceseq}}). 230 | 231 | Events are logged at a time instant and convey specific details of the logging 232 | use case. For example, a network packet being sent or received. This document 233 | declares an abstract Event class ({{abstract-event}}) containing common fields, 234 | which all concrete events derive from. Concrete events are defined by event 235 | schemas that declare or extend a namespace, which contains one or more related 236 | event types or their extensions. For example, this document defines two event 237 | schemas for two generic event namespaces `loglevel` and `simulation` (see 238 | {{generic-event-schema}}). 239 | 240 | # Abstract LogFile Class {#abstract-logfile} 241 | 242 | A Log file is intended to contain a collection of events that are in some way 243 | related. An abstract LogFile class containing fields common to all log files is 244 | defined in {{abstract-logfile-def}}. Each concrete log file schema derives from 245 | this using the CDDL unwrap operator (~) and can extend it by defining semantics 246 | and any custom fields. 247 | 248 | ~~~ cddl 249 | LogFile = { 250 | file_schema: text 251 | serialization_format: text 252 | ? title: text 253 | ? description: text 254 | } 255 | ~~~ 256 | {: #abstract-logfile-def title="LogFile definition"} 257 | 258 | The required "file_schema" field identifies the concrete log file schema. It 259 | MUST have a value that is an absolute URI; see {{schema-uri}} for rules and 260 | guidance. 261 | 262 | The required "serialization_format" field indicates the serialization 263 | format using a media type {{!RFC2046}}. It is case-insensitive. 264 | 265 | In order to make it easier to parse and identify qlog files and their 266 | serialization format, the "file_schema" and "serialization_format" fields and 267 | their values SHOULD be in the first 256 characters/bytes of the resulting log 268 | file. 269 | 270 | The optional "title" and "description" fields provide additional free-text 271 | information about the file. 272 | 273 | ## Concrete Log File Schema URIs {#schema-uri} 274 | 275 | Concrete log file schemas MUST identify themselves using a URI {{!RFC3986}}. 276 | 277 | Log file schemas defined by RFCs MUST register a URI in the "qlog log file 278 | schema URIs" registry and SHOULD use a URN of the form 279 | `urn:ietf:params:qlog:file:`, where `` is 280 | a globally-unique text name using only characters in the URI unreserved range; 281 | see {{Section 2.3 of RFC3986}}. This document registers 282 | `urn:ietf:params:qlog:file:contained` ({{qlog-file-schema}}) and 283 | `urn:ietf:params:qlog:file:sequential` ({{qlog-file-seq-schema}}). 284 | 285 | Private or non-standard log file schemas MAY register a URI in the "qlog log 286 | file schema URIs" registry but MUST NOT use a URN of the form 287 | `urn:ietf:params:qlog:file:`. URIs that contain a domain name 288 | SHOULD also contain a month-date in the form mmyyyy. For example, 289 | "https://example.org/072024/globallyuniquelogfileschema". The definition of the 290 | log file schema and assignment of the URI MUST have been authorized by the owner 291 | of the domain name on or very close to that date. This avoids problems when 292 | domain names change ownership. The URI does not need to be dereferencable, 293 | allowing for confidential use or to cover the case where the log file schema 294 | continues to be used after the organization that defined them ceases to exist. 295 | 296 | The "qlog log file schema URIs" registry operates under the Expert Review 297 | policy, per {{Section 4.5 of !RFC8126}}. When reviewing requests, the expert 298 | MUST check that the URI is appropriate to the concrete log file schema and 299 | satisfies the requirements in this section. A request to register a private or 300 | non-standard log file schema URI using a URN of the form 301 | `urn:ietf:params:qlog:file:` MUST be rejected. 302 | 303 | Registration requests should use the template defined in {{iana}}. 304 | 305 | # QlogFile schema {#qlog-file-schema} 306 | 307 | A qlog file using the QlogFile schema can contain several individual traces and 308 | logs from multiple vantage points that are in some way related. The top-level 309 | element in this schema defines only a small set of "header" fields and an array 310 | of component traces. This is defined in {{qlog-file-def}} as: 311 | 312 | ~~~ cddl 313 | QlogFile = { 314 | ~LogFile 315 | ? traces: [+ Trace / 316 | TraceError] 317 | } 318 | ~~~ 319 | {: #qlog-file-def title="QlogFile definition"} 320 | 321 | The QlogFile schema URI is `urn:ietf:params:qlog:file:contained`. 322 | 323 | QlogFile extends LogFile using the CDDL unwrap operator (~), which copies the 324 | fields presented in {{abstract-logfile}}. Additionally, the optional "traces" 325 | field contains an array of qlog traces ({{trace}}), each of which contain 326 | metadata and an array of qlog events ({{abstract-event}}). 327 | 328 | The default serialization format for QlogFile is JSON; see {{format-json}} for 329 | guidance on populating the "serialization_format" field and other 330 | considerations. Where a qlog file is serialized to a JSON format, one of the 331 | downsides is that it is inherently a non-streamable format. Put differently, it 332 | is not possible to simply append new qlog events to a log file without "closing" 333 | this file at the end by appending "]}]}". Without these closing tags, most JSON 334 | parsers will be unable to parse the file entirely. The alternative QlogFileSeq 335 | ({{qlog-file-seq-schema}}) is better suited to streaming use cases. 336 | 337 | JSON serialization example: 338 | 339 | ~~~ 340 | { 341 | "file_schema": "urn:ietf:params:qlog:file:contained", 342 | "serialization_format": "application/qlog+json", 343 | "title": "Name of this particular qlog file (short)", 344 | "description": "Description for this group of traces (long)", 345 | "traces": [...] 346 | } 347 | ~~~ 348 | {: #qlog-file-ex title="QlogFile example"} 349 | 350 | ## Traces 351 | 352 | It can be advantageous to group several related qlog traces together in a single 353 | file. For example, it is possible to simultaneously perform logging on the 354 | client, on the server, and on a single point on their common network path. For 355 | analysis, it is useful to aggregate these three individual traces together into 356 | a single file, so it can be uniquely stored, transferred, and annotated. 357 | 358 | The QlogFile "traces" field is an array that contains a list of individual qlog 359 | traces. When capturing a qlog at a vantage point, it is expected that the traces 360 | field contains a single entry. Files can be aggregated, for example as part of a 361 | post-processing operation, by copying the traces in component to files into the 362 | combined "traces" array of a new, aggregated qlog file. 363 | 364 | ## Trace {#trace} 365 | 366 | The exact conceptual definition of a Trace can be fluid. For example, a trace 367 | could contain all events for a single connection, for a single endpoint, for a 368 | single measurement interval, for a single protocol, etc. In the normal use case 369 | however, a trace is a log of a single data flow collected at a single location 370 | or vantage point. For example, for QUIC, a single trace only contains events for 371 | a single logical QUIC connection for either the client or the server. 372 | 373 | A Trace contains some metadata in addition to qlog events, defined in 374 | {{trace-def}} as: 375 | 376 | ~~~ cddl 377 | Trace = { 378 | ? title: text 379 | ? description: text 380 | ? common_fields: CommonFields 381 | ? vantage_point: VantagePoint 382 | event_schemas: [+text] 383 | events: [* Event] 384 | } 385 | ~~~ 386 | {: #trace-def title="Trace definition"} 387 | 388 | The optional "title" and "description" fields provide additional free-text 389 | information about the trace. 390 | 391 | The optional "common_fields" field is described in {{common-fields}}. 392 | 393 | The optional "vantage_point" field is described in {{vantage-point}}. 394 | 395 | The required "event_schemas" field contains event schema URIs that identify 396 | concrete event namespaces and their associated types recorded in the "events" 397 | field. Requirements and guidelines are defined in {{event-types-and-schema}}. 398 | 399 | The semantics and context of the trace can mainly be deduced from the entries in 400 | the "common_fields" list and "vantage_point" field. 401 | 402 | JSON serialization example: 403 | 404 | ~~~~~~~~ 405 | { 406 | "title": "Name of this particular trace (short)", 407 | "description": "Description for this trace (long)", 408 | "common_fields": { 409 | "ODCID": "abcde1234", 410 | "time_format": "relative_to_epoch", 411 | "reference_time": { 412 | "clock_type": "system", 413 | "epoch": "1970-01-01T00:00:00.000Z" 414 | }, 415 | }, 416 | "vantage_point": { 417 | "name": "backend-67", 418 | "type": "server" 419 | }, 420 | "event_schemas": ["urn:ietf:params:qlog:events:quic"], 421 | "events": [...] 422 | } 423 | ~~~~~~~~ 424 | {: #trace-ex title="Trace example"} 425 | 426 | ## TraceError 427 | 428 | A TraceError indicates that an attempt to find/convert a file for inclusion in 429 | the aggregated qlog was made, but there was an error during the process. Rather 430 | than silently dropping the erroneous file, it can be explicitly included in the 431 | qlog file as an entry in the "traces" array, defined in {{trace-error-def}} as: 432 | 433 | ~~~ cddl 434 | TraceError = { 435 | error_description: text 436 | 437 | ; the original URI used for attempted find of the file 438 | ? uri: text 439 | ? vantage_point: VantagePoint 440 | } 441 | ~~~ 442 | {: #trace-error-def title="TraceError definition"} 443 | 444 | JSON serialization example: 445 | 446 | ~~~~~~~ 447 | { 448 | "error_description": "File could not be found", 449 | "uri": "/srv/traces/today/latest.qlog", 450 | "vantage_point": { type: "server" } 451 | } 452 | ~~~~~~~ 453 | {: #trace-error-ex title="TraceError example"} 454 | 455 | Note that another way to combine events of different traces in a single qlog file 456 | is through the use of the "group_id" field, discussed in {{group-ids}}. 457 | 458 | # QlogFileSeq schema {#qlog-file-seq-schema} 459 | 460 | A qlog file using the QlogFileSeq schema can be serialized to a streamable JSON 461 | format called JSON Text Sequences (JSON-SEQ) ({{!RFC7464}}). The top-level 462 | element in this schema defines only a small set of "header" fields and an array 463 | of component traces. This is defined in {{qlog-file-def}} as: 464 | 465 | ~~~ cddl 466 | QlogFileSeq = { 467 | ~LogFile 468 | trace: TraceSeq 469 | } 470 | ~~~ 471 | {: #qlog-file-seq-def title="QlogFileSeq definition"} 472 | 473 | The QlogFileSeq schema URI is `urn:ietf:params:qlog:file:sequential`. 474 | 475 | QlogFile extends LogFile using the CDDL unwrap operator (~), which copies the 476 | fields presented in {{abstract-logfile}}. Additionally, the required "trace" 477 | field contains a singular trace ({{trace}}). All qlog events in the file are 478 | related to this trace; see {{traceseq}}. 479 | 480 | See {{format-json-seq}} for guidance on populating the "serialization_format" 481 | field and other serialization considerations. 482 | 483 | JSON-SEQ serialization example: 484 | 485 | ~~~~~~~~ 486 | // list of qlog events, serialized in accordance with RFC 7464, 487 | // starting with a Record Separator character and ending with a 488 | // newline. 489 | // For display purposes, Record Separators are rendered as 490 | 491 | { 492 | "file_schema": "urn:ietf:params:qlog:file:sequential", 493 | "serialization_format": "application/qlog+json-seq", 494 | "title": "Name of JSON Text Sequence qlog file (short)", 495 | "description": "Description for this trace file (long)", 496 | "trace": { 497 | "common_fields": { 498 | "group_id":"127ecc830d98f9d54a42c4f0842aa87e181a", 499 | "time_format": "relative_to_epoch", 500 | "reference_time": { 501 | "clock_type": "system", 502 | "epoch": "1970-01-01T00:00:00.000Z" 503 | }, 504 | }, 505 | "vantage_point": { 506 | "name":"backend-67", 507 | "type":"server" 508 | }, 509 | "event_schemas": ["urn:ietf:params:qlog:events:quic", 510 | "urn:ietf:params:qlog:events:http3"] 511 | } 512 | } 513 | {"time": 2, "name": "quic:parameters_set", "data": { ... } } 514 | {"time": 7, "name": "quic:packet_sent", "data": { ... } } 515 | ... 516 | ~~~~~~~~ 517 | {: #json-seq-ex title="Top-level element"} 518 | 519 | ## TraceSeq {#traceseq} 520 | 521 | TraceSeq is used with QlogFileSeq. It is conceptually similar to a Trace, with 522 | the exception that qlog events are not contained within it, but rather appended 523 | after it in a QlogFileSeq. 524 | 525 | ~~~ cddl 526 | TraceSeq = { 527 | ? title: text 528 | ? description: text 529 | ? common_fields: CommonFields 530 | ? vantage_point: VantagePoint 531 | event_schemas: [+text] 532 | } 533 | ~~~ 534 | {: #trace-seq-def title="TraceSeq definition"} 535 | 536 | # VantagePoint {#vantage-point} 537 | 538 | A VantagePoint describes the vantage point from which a trace originates, 539 | defined in {{vantage-point-def}} as: 540 | 541 | ~~~ cddl 542 | VantagePoint = { 543 | ? name: text 544 | type: VantagePointType 545 | ? flow: VantagePointType 546 | } 547 | 548 | ; client = endpoint which initiates the connection 549 | ; server = endpoint which accepts the connection 550 | ; network = observer in between client and server 551 | VantagePointType = "client" / 552 | "server" / 553 | "network" / 554 | "unknown" 555 | ~~~ 556 | {: #vantage-point-def title="VantagePoint definition"} 557 | 558 | JSON serialization examples: 559 | 560 | ~~~~~~~~ 561 | { 562 | "name": "aioquic client", 563 | "type": "client" 564 | } 565 | 566 | { 567 | "name": "wireshark trace", 568 | "type": "network", 569 | "flow": "client" 570 | } 571 | ~~~~~~~~ 572 | {: #vantage-point-ex title="VantagePoint example"} 573 | 574 | The flow field is only required if the type is "network" (for example, the trace 575 | is generated from a packet capture). It is used to disambiguate events like 576 | "packet sent" and "packet received". This is indicated explicitly because for 577 | multiple reasons (e.g., privacy) data from which the flow direction can be 578 | otherwise inferred (e.g., IP addresses) might not be present in the logs. 579 | 580 | Meaning of the different values for the flow field: 581 | 582 | * "client" indicates that this vantage point follows client data flow semantics (a 583 | "packet sent" event goes in the direction of the server). 584 | * "server" indicates that this vantage point follow server data flow semantics (a 585 | "packet sent" event goes in the direction of the client). 586 | * "unknown" indicates that the flow's direction is unknown. 587 | 588 | Depending on the context, tools confronted with "unknown" values in the 589 | vantage_point can either try to heuristically infer the semantics from 590 | protocol-level domain knowledge (e.g., in QUIC, the client always sends the 591 | first packet) or give the user the option to switch between client and server 592 | perspectives manually. 593 | 594 | # Abstract Event Class {#abstract-event} 595 | 596 | Events are logged at a time instant and convey specific details of the logging 597 | use case. An abstract Event class containing fields common to all events is 598 | defined in {{event-def}}. 599 | 600 | ~~~ cddl 601 | Event = { 602 | time: float64 603 | name: text 604 | data: $ProtocolEventData 605 | ? path: PathID 606 | ? time_format: TimeFormat 607 | ? group_id: GroupID 608 | ? system_info: SystemInformation 609 | 610 | ; events can contain any amount of custom fields 611 | * text => any 612 | } 613 | ~~~ 614 | {: #event-def title="Event definition"} 615 | 616 | Each qlog event MUST contain the mandatory fields: "time" 617 | ({{time-based-fields}}), "name" ({{event-types-and-schema}}), and "data" 618 | ({{data-field}}). 619 | 620 | Each qlog event is an instance of a concrete event type that derives from the 621 | abstract Event class; see {{event-types-and-schema}}. They extend it by defining 622 | the specific values and semantics of common fields, in particular the `name` and 623 | `data` fields. Furthermore, they can optionally add custom fields. 624 | 625 | Each qlog event MAY contain the optional fields: "time_format" 626 | ({{time-based-fields}}), path ({{path-field}}) "trigger" ({{trigger-field}}), 627 | and "group_id" ({{group-ids}}). 628 | 629 | Multiple events can appear in a Trace or TraceSeq and they might contain fields 630 | with identical values. It is possible to optimize out this duplication using 631 | "common_fields" ({{common-fields}}). 632 | 633 | Example qlog event: 634 | 635 | ~~~~~~~~ 636 | { 637 | "time": 1553986553572, 638 | 639 | "name": "quic:packet_sent", 640 | "data": { ... }, 641 | 642 | "group_id": "127ecc830d98f9d54a42c4f0842aa87e181a", 643 | 644 | "time_format": "relative_to_epoch", 645 | 646 | "ODCID": "127ecc830d98f9d54a42c4f0842aa87e181a" 647 | } 648 | ~~~~~~~~ 649 | {: #event-ex title="Event example"} 650 | 651 | ## Timestamps {#time-based-fields} 652 | 653 | Each event MUST include a "time" field to indicate the timestamp that it 654 | occurred. It is a duration measured from some point in time; its units depend on the type of clock chosen and system used. Typically however, a millisecond resolution is employed. 655 | There are several options for generating and logging timestamps, these are 656 | governed by the ReferenceTime type (optionally included in the "reference_time" 657 | field contained in a trace's "common_fields" ({{common-fields}})) and TimeFormat 658 | type (optionally included in the "time_format" field contained in the event 659 | itself, or a trace's "common_fields"). 660 | 661 | There is no requirement that events in the same trace use the same time format. 662 | However, using a single time format for related events can make them easier to 663 | analyze. 664 | 665 | The reference time governs from which point in time the "time" field values are measured and is defined as: 666 | 667 | ~~~ cddl 668 | ReferenceTime = { 669 | clock_type: "system" / "monotonic" / text .default "system" 670 | epoch: RFC3339DateTime / "unknown" .default "1970-01-01T00:00:00.000Z" 671 | 672 | ? wall_clock_time: RFC3339DateTime 673 | } 674 | 675 | RFC3339DateTime = text 676 | ~~~ 677 | {: #reference-time-def title="ReferenceTime definition"} 678 | 679 | The required "clock_type" field represents the type of clock used for time 680 | measurements. The value "system" represents a clock that uses system time, 681 | commonly measured against a chosen or well-known epoch. However, depending on the system, System time can potentially jump forward or back. In contrast, a clock using monotonic time is generally guaranteed to never go backwards. The value "monotonic" represents such a clock. 682 | 683 | The required "epoch" field is the start of the ReferenceTime. When using the 684 | "system" clock type, the epoch field SHOULD have a date/time value using the 685 | format defined in {{!RFC3339}}. However, the value "unknown" MAY be used. 686 | 687 | When using the "monotonic" clock type, the epoch field MUST have the value 688 | "unknown". 689 | 690 | The optional "wall_clock_time" field can be used to provide an approximate 691 | date/time value that logging commenced at if the epoch value is "unknown". It uses 692 | the format defined in {{!RFC3339}}. Note that conversion of timestamps to 693 | calendar time based on wall clock times cannot be safely relied on. 694 | 695 | The time format details how "time" values are encoded relative to the reference time and is defined as: 696 | 697 | ~~~ cddl 698 | TimeFormat = "relative_to_epoch" / 699 | "relative_to_previous_event" .default "relative_to_epoch" 700 | ~~~ 701 | {: #time-format-def title="TimeFormat definition"} 702 | 703 | relative_to_epoch: 704 | : A duration relative to the ReferenceTime "epoch" field. This approach uses the 705 | largest amount of characters. It is good for stateless loggers. This is the default value of the "time_format" field. 706 | 707 | relative_to_previous_event: 708 | : A delta-encoded value, based on the previously logged value. The first event 709 | in a trace is always relative to the ReferenceTime. This approach uses the 710 | least amount of characters. It is suitable for stateful loggers. 711 | 712 | Events in each individual trace SHOULD be logged in strictly ascending timestamp 713 | order (though not necessarily absolute value, for the "relative_to_previous_event" 714 | format). Tools MAY sort all events on the timestamp before processing them, 715 | though are not required to (as this could impose a significant processing 716 | overhead). This can be a problem especially for multi-threaded and/or streaming 717 | loggers, who could consider using a separate post-processor to order qlog events 718 | in time if a tool do not provide this feature. 719 | 720 | Tools SHOULD NOT assume the ability to derive the absolute calendar timestamp of an event 721 | from qlog traces. Tools should not rely on timestamps to be consistent across 722 | traces, even those generated by the same logging endpoint. For reasons of 723 | privacy, the reference time MAY have minimization or anonymization applied. 724 | 725 | Example of a log using the relative_to_epoch format: 726 | 727 | ~~~ 728 | "common_fields": { 729 | "time_format": "relative_to_epoch", 730 | "reference_time": { 731 | "clock_type": "system", 732 | "epoch": "1970-01-01T00:00:00.000Z" 733 | }, 734 | }, 735 | "events": [ 736 | { 737 | "time": 1553986553572, 738 | "name": "quic:packet_received", 739 | "data": { ... }, 740 | }, 741 | { 742 | "time": 1553986553577, 743 | "name": "quic:packet_received", 744 | "data": { ... }, 745 | }, 746 | { 747 | "time": 1553986553587, 748 | "name": "quic:packet_received", 749 | "data": { ... }, 750 | }, 751 | { 752 | "time": 1553986553597, 753 | "name": "quic:packet_received", 754 | "data": { ... }, 755 | }, 756 | ] 757 | ~~~ 758 | {: #rel-epoch-time-ex title="Relative to epoch timestamps"} 759 | 760 | Example of a log using the relative_to_previous_event format: 761 | 762 | ~~~ 763 | "common_fields": { 764 | "time_format": "relative_to_previous_event", 765 | "reference_time": { 766 | "clock_type": "system", 767 | "epoch": "1970-01-01T00:00:00.000Z" 768 | }, 769 | }, 770 | "events": [ 771 | { 772 | "time": 1553986553572, 773 | "name": "quic:packet_received", 774 | "data": { ... }, 775 | }, 776 | { 777 | "time": 5, 778 | "name": "quic:packet_received", 779 | "data": { ... }, 780 | }, 781 | { 782 | "time": 10, 783 | "name": "quic:packet_received", 784 | "data": { ... }, 785 | }, 786 | { 787 | "time": 10, 788 | "name": "quic:packet_received", 789 | "data": { ... }, 790 | }, 791 | ] 792 | ~~~ 793 | {: #rel-last-event-time-ex title="Relative-to-previous-event timestamps"} 794 | 795 | Example of a monotonic log using the relative_to_epoch format: 796 | 797 | ~~~ 798 | "common_fields": { 799 | "time_format": "relative_to_epoch", 800 | "reference_time": { 801 | "clock_type": "monotonic", 802 | "epoch": "unknown", 803 | "wall_clock_time": "2024-10-10T10:10:10.000Z" 804 | }, 805 | }, 806 | "events": [ 807 | { 808 | "time": 0, 809 | "name": "quic:packet_received", 810 | "data": { ... }, 811 | }, 812 | { 813 | "time": 5, 814 | "name": "quic:packet_received", 815 | "data": { ... }, 816 | }, 817 | { 818 | "time": 15, 819 | "name": "quic:packet_received", 820 | "data": { ... }, 821 | }, 822 | { 823 | "time": 25, 824 | "name": "quic:packet_received", 825 | "data": { ... }, 826 | }, 827 | ] 828 | ~~~ 829 | {: #mono-time-ex title="Monotonic timestamps"} 830 | 831 | 832 | ## Path {#path-field} 833 | 834 | A qlog event can be associated with a single "network path" (usually, but not 835 | always, identified by a 4-tuple of IP addresses and ports). In many cases, the 836 | path will be the same for all events in a given trace, and does not need to be 837 | logged explicitly with each event. In this case, the "path" field can be omitted 838 | (in which case the default value of "" is assumed) or reflected in 839 | "common_fields" instead (see {{common-fields}}). 840 | 841 | However, in some situations, such as during QUIC's Connection Migration or when 842 | using Multipath features, it is useful to be able to split events across 843 | multiple (concurrent) paths. 844 | 845 | Definition: 846 | 847 | ~~~ cddl 848 | PathID = text .default "" 849 | ~~~ 850 | {: #path-def title="PathID definition"} 851 | 852 | 853 | The "path" field is an identifier that is associated with a single network path. 854 | This document intentionally does not define further how to choose this 855 | identifier's value per-path or how to potentially log other parameters that can 856 | be associated with such a path. This is left for other documents. Implementers 857 | are free to encode path information directly into the PathID or to log 858 | associated info in a separate event. For example, QUIC has the "path_assigned" 859 | event to couple the PathID value to a specific path configuration, see 860 | {{QLOG-QUIC}}. 861 | 862 | ## Grouping {#group-ids} 863 | 864 | As discussed in {{trace}}, a single qlog file can contain several traces taken 865 | from different vantage points. However, a single trace from one endpoint can also 866 | contain events from a variety of sources. For example, a server implementation 867 | might choose to log events for all incoming connections in a single large 868 | (streamed) qlog file. As such, a method for splitting up events belonging 869 | to separate logical entities is required. 870 | 871 | The simplest way to perform this splitting is by associating a "group id" 872 | to each event that indicates to which conceptual "group" each event belongs. A 873 | post-processing step can then extract events per group. However, this group 874 | identifier can be highly protocol and context-specific. In the example above, 875 | the QUIC "Original Destination Connection ID" could be used to uniquely identify a 876 | connection. As such, they might add a "ODCID" field to each event. However, a 877 | middlebox logging IP or TCP traffic might rather use four-tuples to identify 878 | connections, and add a "four_tuple" field. 879 | 880 | As such, to provide consistency and ease of tooling in cross-protocol and 881 | cross-context setups, qlog instead defines the common "group_id" field, which 882 | contains a string value. Implementations are free to use their preferred string 883 | serialization for this field, so long as it contains a unique value per logical 884 | group. Some examples can be seen in {{group-id-ex}}. 885 | 886 | ~~~ cddl 887 | GroupID = text 888 | ~~~ 889 | {: #group-id-def title="GroupID definition"} 890 | 891 | JSON serialization example for events grouped by four tuples 892 | and QUIC connection IDs: 893 | 894 | ~~~~~~~~ 895 | "events": [ 896 | { 897 | "time": 1553986553579, 898 | "group_id": "ip1=2001:67c:1232:144:9498:6df6:f450:110b, 899 | ip2=2001:67c:2b0:1c1::198,port1=59105,port2=80", 900 | "name": "quic:packet_received", 901 | "data": { ... } 902 | }, 903 | { 904 | "time": 1553986553581, 905 | "group_id": "127ecc830d98f9d54a42c4f0842aa87e181a", 906 | "name": "quic:packet_sent", 907 | "data": { ... } 908 | } 909 | ] 910 | ~~~~~~~~ 911 | {: #group-id-ex title="GroupID example"} 912 | 913 | Note that in some contexts (for example a Multipath transport protocol) it might 914 | make sense to add additional contextual per-event fields (for example PathID, 915 | see {{path-field}}), rather than use the group_id field for that purpose. 916 | 917 | Note also that, typically, a single trace only contains events belonging to a 918 | single logical group (for example, an individual QUIC connection). As such, 919 | instead of logging the "group_id" field with an identical value for each event 920 | instance, this field is typically logged once in "common_fields", see 921 | {{common-fields}}. 922 | 923 | ## SystemInformation 924 | 925 | The "system_info" field can be used to record system-specific details related to an 926 | event. This is useful, for instance, where an application splits work across 927 | CPUs, processes, or threads and events for a single trace occur on potentially 928 | different combinations thereof. Each field is optional to support deployment 929 | diversity. 930 | 931 | ~~~ cddl 932 | SystemInformation = { 933 | ? processor_id: uint32 934 | ? process_id: uint32 935 | ? thread_id: uint32 936 | } 937 | ~~~ 938 | 939 | ## CommonFields {#common-fields} 940 | 941 | As discussed in the previous sections, information for a typical qlog event 942 | varies in three main fields: "time", "name" and associated data. Additionally, 943 | there are also several more advanced fields that allow mixing events from 944 | different protocols and contexts inside of the same trace (for example 945 | "group_id"). In most "normal" use cases however, the values of these advanced 946 | fields are consistent for each event instance (for example, a single trace 947 | contains events for a single QUIC connection). 948 | 949 | To reduce file size and making logging easier, qlog uses the "common_fields" list 950 | to indicate those fields and their values that are shared by all events in this 951 | component trace. This prevents these fields from being logged for each individual 952 | event. An example of this is shown in {{common-fields-ex}}. 953 | 954 | ~~~~~~~~ 955 | JSON serialization with repeated field values 956 | per-event instance: 957 | 958 | { 959 | "events": [{ 960 | "group_id": "127ecc830d98f9d54a42c4f0842aa87e181a", 961 | "time_format": "relative_to_epoch", 962 | "reference_time": { 963 | "clock_type": "system", 964 | "epoch": "2019-03-29T:22:55:53.572Z" 965 | }, 966 | 967 | "time": 2, 968 | "name": "quic:packet_received", 969 | "data": { ... } 970 | },{ 971 | "group_id": "127ecc830d98f9d54a42c4f0842aa87e181a", 972 | "time_format": "relative_to_epoch", 973 | "reference_time": { 974 | "clock_type": "system", 975 | "epoch": "2019-03-29T:22:55:53.572Z" 976 | }, 977 | 978 | "time": 7, 979 | "name": "http:frame_parsed", 980 | "data": { ... } 981 | } 982 | ] 983 | } 984 | 985 | JSON serialization with repeated field values instead 986 | extracted to common_fields: 987 | 988 | { 989 | "common_fields": { 990 | "group_id": "127ecc830d98f9d54a42c4f0842aa87e181a", 991 | "time_format": "relative_to_epoch", 992 | "reference_time": { 993 | "clock_type": "system", 994 | "epoch": "2019-03-29T:22:55:53.572Z" 995 | }, 996 | }, 997 | "events": [ 998 | { 999 | "time": 2, 1000 | "name": "quic:packet_received", 1001 | "data": { ... } 1002 | },{ 1003 | "time": 7, 1004 | "name": "http:frame_parsed", 1005 | "data": { ... } 1006 | } 1007 | ] 1008 | } 1009 | ~~~~~~~~ 1010 | {: #common-fields-ex title="CommonFields example"} 1011 | 1012 | An event's "common_fields" field is a generic dictionary of key-value pairs, where the 1013 | key is always a string and the value can be of any type, but is typically also a 1014 | string or number. As such, unknown entries in this dictionary MUST be disregarded 1015 | by the user and tools (i.e., the presence of an unknown field is explicitly NOT an 1016 | error). 1017 | 1018 | The list of default qlog fields that are typically logged in common_fields (as 1019 | opposed to as individual fields per event instance) are shown in the listing 1020 | below: 1021 | 1022 | ~~~ cddl 1023 | CommonFields = { 1024 | ? path: PathID 1025 | ? time_format: TimeFormat 1026 | ? reference_time: ReferenceTime 1027 | ? group_id: GroupID 1028 | * text => any 1029 | } 1030 | ~~~ 1031 | {: #common-fields-def title="CommonFields definition"} 1032 | 1033 | Tools MUST be able to deal with these fields being defined either on each event 1034 | individually or combined in common_fields. Note that if at least one event in a 1035 | trace has a different value for a given field, this field MUST NOT be added to 1036 | common_fields but instead defined on each event individually. Good example of such 1037 | fields are "time" and "data", who are divergent by nature. 1038 | 1039 | # Concrete Event Types and Event Schemas {#event-types-and-schema} 1040 | 1041 | Concrete event types, as well as related data types, are grouped in event 1042 | namespaces which in turn are defined in one or multiple event schemas. 1043 | 1044 | As an example, the `QUICPacketSent` and `QUICPacketHeader` event and data types 1045 | would be part of the `quic` namespace, which is defined in an event schema with 1046 | URI `urn:ietf:params:qlog:events:quic`. A later extension that adds a new QUIC 1047 | frame `QUICNewFrame` would also be part of the `quic` namespace, but defined in 1048 | a new event schema with URI 1049 | `urn:ietf:params:qlog:events:quic#new-frame-extension`. 1050 | 1051 | Concrete event types MUST belong to a single event namespace and MUST have a 1052 | registered non-empty identifier of type `text`. 1053 | 1054 | New namespaces MUST have a registered non-empty globally-unique text identifier 1055 | using only characters in the URI unreserved range; see {{Section 2.3 of 1056 | RFC3986}}. Namespaces are mutable and MAY be extended with new events. 1057 | 1058 | The value of a qlog event `name` field MUST be the concatenation of namespace 1059 | identifier, colon (':'), and event type identifier (for example: 1060 | quic:packet_sent). The resulting concatenation MUST be globally unique, so log 1061 | files can contain events from multiple event schemas without the risk of name 1062 | collisions. 1063 | 1064 | A single event schema can contain exactly one of the below: 1065 | 1066 | * A definition for a new event namespace 1067 | * An extension of an existing namespace (adding new events/data types and/or 1068 | extending existing events/data types within the namespace with new fields) 1069 | 1070 | A single document can define multiple event schemas (for example see 1071 | {{generic-event-schema}}). 1072 | 1073 | An event schema MUST have a single URI {{RFC3986}} that MUST be absolute. The 1074 | URI MUST include the namespace identifier. Event schemas that extend an existing 1075 | namespace MUST furthermore include a non-empty globally-unique "extension" 1076 | identifier using a URI fragment (characters after a "#" in the URI) using only 1077 | characters in the URI unreserved range; see {{Section 2.3 of RFC3986}}. 1078 | Registration guidance and requirement for event schema URIs are provided in 1079 | {{event-schema-reg}}. Event schemas by themselves are immutable and MUST NOT be 1080 | extended. 1081 | 1082 | Implementations that record concrete event types SHOULD list all event schemas 1083 | in use. This is achieved by including the appropriate URIs in the 1084 | `event_schemas` field of the Trace ({{trace}}) and TraceSeq ({{traceseq}}) 1085 | classes. The `event_schemas` is a hint to tools about the possible event 1086 | namespaces, their extensions, and the event types/data types contained therein, 1087 | that a qlog trace might contain. The trace MAY still contain event types that do 1088 | not belong to a listed event schema. Inversely, not all event types associated 1089 | with an event schema listed in `event_schemas` are guaranteed to be logged in a 1090 | qlog trace. Tools MUST NOT treat either of these as an error; see {{tooling}}. 1091 | 1092 | In the following hypothetical example, a qlog trace contains events belonging to: 1093 | 1094 | * The two event namespaces defined by event schemas in this document 1095 | ({{generic-event-schema}}). 1096 | * Events in a namespace named `rick` specified in a hypothetical RFC 1097 | * Extentions to the `rick` namespace defined in two separate new event schemas 1098 | (with URI extension identifiers `astley` and `moranis`) 1099 | * Events from three private event schemas, detailing definitions for and 1100 | extensions to two namespaces (`pickle` and `cucumber`) 1101 | 1102 | The standardized schema URIs use a URN format, the private schemas use a URI 1103 | with domain name. 1104 | 1105 | ~~~ 1106 | "event_schemas": [ 1107 | "urn:ietf:params:qlog:events:loglevel", 1108 | "urn:ietf:params:qlog:events:simulation", 1109 | "urn:ietf:params:qlog:events:rick", 1110 | "urn:ietf:params:qlog:events:rick#astley", 1111 | "urn:ietf:params:qlog:events:rick#moranis", 1112 | "https://example.com/032024/pickle.html", 1113 | "https://example.com/032024/pickle.html#lilly", 1114 | "https://example.com/032025/cucumber.html" 1115 | ] 1116 | ~~~ 1117 | {: #event-schemas title="Example event_schemas serialization"} 1118 | 1119 | ## Event Schema URIs {#event-schema-reg} 1120 | 1121 | Event schemas defined by RFCs MUST register all namespaces and concrete event 1122 | types they contain in the "qlog event schema URIs" registry. 1123 | 1124 | Event schemas that define a new namespace SHOULD use a URN of the form 1125 | `urn:ietf:params:qlog:events:`, where `` is globally unique. For example, this document defines two event 1127 | schemas ({{generic-event-schema}}) for two namespaces: `loglevel` and `sim`. 1128 | Other examples of event schema define the `quic` {{QLOG-QUIC}} and `http3` 1129 | {{QLOG-H3}} namespaces. 1130 | 1131 | Event schemas that extend an existing namespace SHOULD use a URN of the form 1132 | `urn:ietf:params:qlog:events:#`, 1133 | where the combination of `` and `` 1134 | is globally unique. 1135 | 1136 | Private or non-standard event schemas MAY be registered in the "qlog event 1137 | schema URIs" registry but MUST NOT use a URN of the forms outlined above. URIs 1138 | that contain a domain name SHOULD also contain a month-date in the form mmyyyy. 1139 | For example, "https://example.org/072024/customeventschema#customextension". The 1140 | definition of the event schema and assignment of the URI MUST have been 1141 | authorized by the owner of the domain name on or very close to that date. This 1142 | avoids problems when domain names change ownership. The URI does not need to be 1143 | dereferencable, allowing for confidential use or to cover the case where the 1144 | event schemas continue to be used after the organization that defined them 1145 | ceases to exist. 1146 | 1147 | The "qlog event schema URIs" registry operates under the Expert Review policy, 1148 | per {{Section 4.5 of !RFC8126}}. When reviewing requests, the expert MUST check 1149 | that the URI is appropriate to the event schema and satisfies the requirements 1150 | in {{event-types-and-schema}} and this section. A request to register a private 1151 | or non-standard schema URI using a URN of the forms reserved for schemas defined 1152 | by an RFC above MUST be rejected. 1153 | 1154 | Registration requests should use the template defined in {{iana}}. 1155 | 1156 | ## Extending the Data Field {#data-field} 1157 | 1158 | An event's "data" field is a generic key-value map (e.g., JSON object). It 1159 | defines the per-event metadata that is to be logged. Its specific subfields and 1160 | their semantics are defined per concrete event type. For example, data field 1161 | definitions for QUIC and HTTP/3 can be found in {{QLOG-QUIC}} and {{QLOG-H3}}. 1162 | 1163 | In order to keep qlog fully extensible, two separate CDDL extension points 1164 | ("sockets" or "plugs") are used to fully define data fields. 1165 | 1166 | Firstly, to allow existing data field definitions to be extended (for example by 1167 | adding an additional field needed for a new protocol feature), a CDDL "group 1168 | socket" is used. This takes the form of a subfield with a name of `* 1169 | $$NAMESPACE-EVENTTYPE-extension`. This field acts as a placeholder that can 1170 | later be replaced with newly defined fields by assigning them to the socket with 1171 | the `//=` operator. Multiple extensions can be assigned to the same group 1172 | socket. An example is shown in {{groupsocket-extension-example}}. 1173 | 1174 | ~~~~~~~~ 1175 | ; original definition in event schema A 1176 | MyNSEventX = { 1177 | field_a: uint8 1178 | 1179 | * $$myns-eventx-extension 1180 | } 1181 | 1182 | ; later extension of EventX in event schema B 1183 | $$myns-eventx-extension //= ( 1184 | ? additional_field_b: bool 1185 | ) 1186 | 1187 | ; another extension of EventX in event schema C 1188 | $$myns-eventx-extension //= ( 1189 | ? additional_field_c: text 1190 | ) 1191 | 1192 | ; if schemas A, B and C are then used in conjunction, 1193 | ; the combined MyNSEventX CDDL is equivalent to this: 1194 | MyNSEventX = { 1195 | field_a: uint8 1196 | 1197 | ? additional_field_b: bool 1198 | ? additional_field_c: text 1199 | } 1200 | ~~~~~~~~ 1201 | {: #groupsocket-extension-example title="Example of using a generic CDDL group socket to extend an existing event data definition"} 1202 | 1203 | Secondly, to allow documents to define fully new event data field definitions 1204 | (as opposed to extend existing ones), a CDDL "type socket" is used. For this 1205 | purpose, the type of the "data" field in the qlog Event type (see {{event-def}}) 1206 | is the extensible `$ProtocolEventData` type. This field acts as an open enum of 1207 | possible types that are allowed for the data field. As such, any new event data 1208 | field is defined as its own CDDL type and later merged with the existing 1209 | `$ProtocolEventData` enum using the `/=` extension operator. Any generic 1210 | key-value map type can be assigned to `$ProtocolEventData`. The example in 1211 | {{protocoleventdata-def}} demonstrates `$ProtocolEventData` being extended with 1212 | two types. 1213 | 1214 | ~~~~~~~~ 1215 | ; We define two new concrete events in a new event schema 1216 | MyNSEvent1 /= { 1217 | field_1: uint8 1218 | 1219 | * $$myns-event1-extension 1220 | } 1221 | 1222 | MyNSEvent2 /= { 1223 | field_2: bool 1224 | 1225 | * $$myns-event2-extension 1226 | } 1227 | 1228 | ; the events are both merged with the existing 1229 | ; $ProtocolEventData type enum 1230 | $ProtocolEventData /= MyNSEvent1 / MyNSEvent2 1231 | 1232 | ; the "data" field of a qlog event can now also be of type 1233 | ; MyNSEvent1 and MyNSEvent2 1234 | ~~~~~~~~ 1235 | {: #protocoleventdata-def title="ProtocolEventData extension"} 1236 | 1237 | Event schema defining new qlog events MUST properly extend `$ProtocolEventData` 1238 | when defining data fields to enable automated validation of aggregated qlog 1239 | schemas. Furthermore, they SHOULD add a `* $$NAMESPACE-EVENTTYPE-extension` 1240 | extension field to newly defined event data to allow the new events to be 1241 | properly extended by other event schema. 1242 | 1243 | A combined but purely illustrative example of the use of both extension points 1244 | for a conceptual QUIC "packet_sent" event is shown in {{data-ex}}: 1245 | 1246 | ~~~~~~~~ 1247 | ; defined in the main QUIC event schema 1248 | QUICPacketSent = { 1249 | ? packet_size: uint16 1250 | header: QUICPacketHeader 1251 | ? frames:[* QUICFrame] 1252 | 1253 | * $$quic-packetsent-extension 1254 | } 1255 | 1256 | ; Add the event to the global list of recognized qlog events 1257 | $ProtocolEventData /= QUICPacketSent 1258 | 1259 | ; Defined in a separate event schema that describes a 1260 | ; theoretical QUIC protocol extension 1261 | $$quic-packetsent-extension //= ( 1262 | ? additional_field: bool 1263 | ) 1264 | 1265 | ; If both schemas are utilized at the same time, 1266 | ; the following JSON serialization would pass an automated 1267 | ; CDDL schema validation check: 1268 | 1269 | { 1270 | "time": 123456, 1271 | "name": "quic:packet_sent", 1272 | "data": { 1273 | "packet_size": 1280, 1274 | "header": { 1275 | "packet_type": "1RTT", 1276 | "packet_number": 123 1277 | }, 1278 | "frames": [ 1279 | { 1280 | "frame_type": "stream", 1281 | "length": 1000, 1282 | "offset": 456 1283 | }, 1284 | { 1285 | "frame_type": "padding" 1286 | } 1287 | ], 1288 | additional_field: true 1289 | } 1290 | } 1291 | ~~~~~~~~ 1292 | {: #data-ex title="Example of an extended 'data' field for a conceptual QUIC packet_sent event"} 1293 | 1294 | ### Triggers {#trigger-field} 1295 | 1296 | It can be useful to understand the cause or trigger of an event. Sometimes, 1297 | events are caused by a variety of other events and additional information is 1298 | needed to identify the exact details. Commonly, the context of the surrounding 1299 | log messages gives a hint about the cause. However, in highly-parallel and 1300 | optimized implementations, corresponding log messages might be separated in 1301 | time, making it difficult to build an accurate context. 1302 | 1303 | Including a "trigger" as part of the event itself is one method for providing 1304 | fine-grained information without much additional overhead. In circumstances 1305 | where a trigger is useful, it is RECOMMENDED for the purpose of consistency that 1306 | the event data definition contains an optional field named "trigger", holding a 1307 | string value. 1308 | 1309 | For example, the QUIC "packet_dropped" event ({{Section 5.7 of QLOG-QUIC}}) 1310 | includes a trigger field that identifies the precise reason why a QUIC packet 1311 | was dropped: 1312 | 1313 | ~~~~~~~~ 1314 | QUICPacketDropped = { 1315 | 1316 | ; Primarily packet_type should be filled here, 1317 | ; as other fields might not be decrypteable or parseable 1318 | ? header: PacketHeader 1319 | ? raw: RawInfo 1320 | ? datagram_id: uint32 1321 | ? details: {* text => any} 1322 | ? trigger: 1323 | "internal_error" / 1324 | "rejected" / 1325 | "unsupported" / 1326 | "invalid" / 1327 | "duplicate" / 1328 | "connection_unknown" / 1329 | "decryption_failure" / 1330 | "key_unavailable" / 1331 | "general" 1332 | 1333 | * $$quic-packetdropped-extension 1334 | } 1335 | ~~~~~~~~ 1336 | {: #trigger-ex title="Trigger example"} 1337 | 1338 | ## Event Importance Levels {#importance} 1339 | 1340 | Depending on how events are designed, it may be that several events allow the 1341 | logging of similar or overlapping data. For example the separate QUIC 1342 | `connection_started` event overlaps with the more generic 1343 | `connection_state_updated`. In these cases, it is not always clear which event 1344 | should be logged or used, and which event should take precedence if e.g., both are 1345 | present and provide conflicting information. 1346 | 1347 | To aid in this decision making, qlog defines three event importance levels, in 1348 | decreasing order of importance and expected usage: 1349 | 1350 | * Core 1351 | * Base 1352 | * Extra 1353 | 1354 | Concrete event types SHOULD define an importance level. 1355 | 1356 | Core-level events SHOULD be present in all qlog files for a given protocol. 1357 | These are typically tied to basic packet and frame parsing and creation, as well 1358 | as listing basic internal metrics. Tool implementers SHOULD expect and add 1359 | support for these events, though SHOULD NOT expect all Core events to be present 1360 | in each qlog trace. 1361 | 1362 | Base-level events add additional debugging options and MAY be present in qlog 1363 | files. Most of these can be implicitly inferred from data in Core events (if 1364 | those contain all their properties), but for many it is better to log the events 1365 | explicitly as well, making it clearer how the implementation behaves. These 1366 | events are for example tied to passing data around in buffers, to how internal 1367 | state machines change, and used to help show when decisions are actually made 1368 | based on received data. Tool implementers SHOULD at least add support for 1369 | showing the contents of these events, if they do not handle them explicitly. 1370 | 1371 | Extra-level events are considered mostly useful for low-level debugging of the 1372 | implementation, rather than the protocol. They allow more fine-grained tracking 1373 | of internal behavior. As such, they MAY be present in qlog files and tool 1374 | implementers MAY add support for these, but they are not required to. 1375 | 1376 | Note that in some cases, implementers might not want to log for example data 1377 | content details in Core-level events due to performance or privacy considerations. 1378 | In this case, they SHOULD use (a subset of) relevant Base-level events instead to 1379 | ensure usability of the qlog output. As an example, implementations that do not 1380 | log QUIC `packet_received` events and thus also not which (if any) ACK frames the 1381 | packet contains, SHOULD log `packets_acked` events instead. 1382 | 1383 | Finally, for event types whose data (partially) overlap with other event types' 1384 | definitions, where necessary the event definition document should include explicit 1385 | guidance on which to use in specific situations. 1386 | 1387 | ## Tooling Expectations 1388 | 1389 | qlog is an extensible format and it is expected that new event schema will 1390 | emerge that define new namespaces, event types, event fields (e.g., a field 1391 | indicating an event's privacy properties), as well as values for the "trigger" 1392 | property within the "data" field, or other member fields of the "data" field, as 1393 | they see fit. 1394 | 1395 | It SHOULD NOT be expected that general-purpose tools will recognize or visualize 1396 | all forms of qlog extension. Tools SHOULD allow for the presence of unknown 1397 | event fields and make an effort to visualize even unknown data if possible, 1398 | otherwise they MUST ignore it. 1399 | 1400 | ## Further Design Guidance 1401 | 1402 | There are several ways of defining concrete event types. In practice, two main 1403 | types of approach have been observed: a) those that map directly to concepts 1404 | seen in the protocols (e.g., `packet_sent`) and b) those that act as aggregating 1405 | events that combine data from several possible protocol behaviors or code paths 1406 | into one (e.g., `parameters_set`). The latter are typically used as a means to 1407 | reduce the amount of unique event definitions, as reflecting each possible 1408 | protocol event as a separate qlog entity would cause an explosion of event 1409 | types. 1410 | 1411 | Additionally, logging duplicate data is typically prevented as much as possible. 1412 | For example, packet header values that remain consistent across many packets are 1413 | split into separate events (for example `spin_bit_updated` or 1414 | `connection_id_updated` for QUIC). 1415 | 1416 | Finally, when logging additional state change events, those state changes can 1417 | often be directly inferred from data on the wire (for example flow control limit 1418 | changes). As such, if the implementation is bug-free and spec-compliant, logging 1419 | additional events is typically avoided. Exceptions have been made for common 1420 | events that benefit from being easily identifiable or individually logged (for 1421 | example `packets_acked`). 1422 | 1423 | # The Generic Event Schemas {#generic-event-schema} 1424 | 1425 | The two following generic event schemas define two namespaces and several 1426 | concrete event types that are common across protocols, applications, and use 1427 | cases. 1428 | 1429 | ## Loglevel events {#loglevel-events} 1430 | 1431 | In typical logging setups, users utilize a discrete number of well-defined 1432 | logging categories, levels or severities to log freeform (string) data. The 1433 | loglevel event namespace replicates this approach to allow implementations to 1434 | fully replace their existing text-based logging by qlog. This is done by 1435 | providing events to log generic strings for the typical well-known logging 1436 | levels (error, warning, info, debug, verbose). The namespace identifier is 1437 | "loglevel". The event schema URI is `urn:ietf:params:qlog:events:loglevel`. 1438 | 1439 | ~~~ cddl 1440 | LogLevelEventData = LogLevelError / 1441 | LogLevelWarning / 1442 | LogLevelInfo / 1443 | LogLevelDebug / 1444 | LogLevelVerbose 1445 | 1446 | $ProtocolEventData /= LogLevelEventData 1447 | ~~~ 1448 | {: #loglevel-events-def title="LogLevelEventData and ProtocolEventData extension"} 1449 | 1450 | The event types are further defined below, their identifier is the heading name. 1451 | 1452 | ### error 1453 | 1454 | Used to log details of an internal error that might not get reflected on the 1455 | wire. It has Core importance level; see {{importance}}. 1456 | 1457 | ~~~ cddl 1458 | LogLevelError = { 1459 | ? code: uint64 1460 | ? message: text 1461 | 1462 | * $$loglevel-error-extension 1463 | } 1464 | ~~~ 1465 | {: #loglevel-error-def title="LogLevelError definition"} 1466 | 1467 | ### warning 1468 | 1469 | Used to log details of an internal warning that might not get reflected on the 1470 | wire. It has Base importance level; see {{importance}}. 1471 | 1472 | ~~~ cddl 1473 | LogLevelWarning = { 1474 | ? code: uint64 1475 | ? message: text 1476 | 1477 | * $$loglevel-warning-extension 1478 | } 1479 | ~~~ 1480 | {: #loglevel-warning-def title="LogLevelWarning definition"} 1481 | 1482 | ### info 1483 | 1484 | Used mainly for implementations that want to use qlog as their one and only 1485 | logging format but still want to support unstructured string messages. The event 1486 | has Extra importance level; see {{importance}}. 1487 | 1488 | ~~~ cddl 1489 | LogLevelInfo = { 1490 | message: text 1491 | 1492 | * $$loglevel-info-extension 1493 | } 1494 | ~~~ 1495 | {: #loglevel-info-def title="LogLevelInfo definition"} 1496 | 1497 | ### debug 1498 | 1499 | Used mainly for implementations that want to use qlog as their one and only 1500 | logging format but still want to support unstructured string messages. The event 1501 | has Extra importance level; see {{importance}}. 1502 | 1503 | ~~~ cddl 1504 | LogLevelDebug = { 1505 | message: text 1506 | 1507 | * $$loglevel-debug-extension 1508 | } 1509 | ~~~ 1510 | {: #loglevel-debug-def title="LogLevelDebug definition"} 1511 | 1512 | ### verbose 1513 | 1514 | Used mainly for implementations that want to use qlog as their one and only 1515 | logging format but still want to support unstructured string messages. The event 1516 | has Extra importance level; see {{importance}}. 1517 | 1518 | ~~~ cddl 1519 | LogLevelVerbose = { 1520 | message: text 1521 | 1522 | * $$loglevel-verbose-extension 1523 | } 1524 | ~~~ 1525 | {: #loglevel-verbose-def title="LogLevelVerbose definition"} 1526 | 1527 | ## Simulation Events {#sim-events} 1528 | 1529 | When evaluating a protocol implementation, one typically sets up a series of 1530 | interoperability or benchmarking tests, in which the test situations can change 1531 | over time. For example, the network bandwidth or latency can vary during the 1532 | test, or the network can be fully disable for a short time. In these setups, it 1533 | is useful to know when exactly these conditions are triggered, to allow for 1534 | proper correlation with other events. This namespace defines event types to 1535 | allow logging of such simulation metadata and its identifier is "simulation". 1536 | The event schema URI is `urn:ietf:params:qlog:events:simulation`. 1537 | 1538 | ~~~ cddl 1539 | SimulationEventData = SimulationScenario / 1540 | SimulationMarker 1541 | 1542 | $ProtocolEventData /= SimulationEventData 1543 | ~~~ 1544 | {: #sim-events-def title="SimulationEventData and ProtocolEventData extension"} 1545 | 1546 | The event types are further defined below, their identifier is the heading name. 1547 | 1548 | ### scenario 1549 | 1550 | Used to specify which specific scenario is being tested at this particular 1551 | instance. This supports, for example, aggregation of several simulations into 1552 | one trace (e.g., split by `group_id`). It has Extra importance level; see 1553 | {{importance}}. 1554 | 1555 | ~~~ cddl 1556 | SimulationScenario = { 1557 | ? name: text 1558 | ? details: {* text => any } 1559 | 1560 | * $$simulation-scenario-extension 1561 | } 1562 | ~~~ 1563 | {: #simulation-scenario-def title="SimulationScenario definition"} 1564 | 1565 | ### marker 1566 | 1567 | Used to indicate when specific emulation conditions are triggered at set times 1568 | (e.g., at 3 seconds in 2% packet loss is introduced, at 10s a NAT rebind is 1569 | triggered). It has Extra importance level; see {{importance}}. 1570 | 1571 | ~~~ cddl 1572 | SimulationMarker = { 1573 | ? type: text 1574 | ? message: text 1575 | 1576 | * $$simulation-marker-extension 1577 | } 1578 | ~~~ 1579 | {: #simulation-marker-def title="SimulationMarker definition"} 1580 | 1581 | 1582 | # Raw packet and frame information {#raw-info} 1583 | 1584 | While qlog is a high-level logging format, it also allows the inclusion of most 1585 | raw wire image information, such as byte lengths and byte values. This is useful 1586 | when for example investigating or tuning packetization behavior or determining 1587 | encoding/framing overheads. However, these fields are not always necessary, can 1588 | take up considerable space, and can have a considerable privacy and security 1589 | impact (see {{privacy}}). Where applicable, these fields are grouped in a 1590 | separate, optional, field named "raw" of type RawInfo. The exact definition of 1591 | entities, headers, trailers and payloads depend on the protocol used. 1592 | 1593 | ~~~ cddl 1594 | RawInfo = { 1595 | 1596 | ; the full byte length of the entity (e.g., packet or frame), 1597 | ; including possible headers and trailers 1598 | ? length: uint64 1599 | 1600 | ; the byte length of the entity's payload, 1601 | ; excluding possible headers or trailers 1602 | ? payload_length: uint64 1603 | 1604 | ; the (potentially truncated) contents of the full entity, 1605 | ; including headers and possibly trailers 1606 | ? data: hexstring 1607 | } 1608 | ~~~ 1609 | {: #raw-info-def title="RawInfo definition"} 1610 | 1611 | The RawInfo:data field can be truncated for privacy or security purposes, see 1612 | {{truncated-values}}. In this case, the length and payload_length fields should 1613 | still indicate the non-truncated lengths when used for debugging purposes. 1614 | 1615 | This document does not specify explicit header_length or trailer_length fields. 1616 | In protocols without trailers, header_length can be calculated by subtracting 1617 | the payload_length from the length. In protocols with trailers (e.g., QUIC's 1618 | AEAD tag), event definition documents SHOULD define how to support header_length 1619 | calculation. 1620 | 1621 | # Serializing qlog {#concrete-formats} 1622 | 1623 | qlog schema definitions in this document are intentionally agnostic to 1624 | serialization formats. The choice of format is an implementation decision. 1625 | 1626 | Other documents related to qlog (for example event definitions for specific 1627 | protocols), SHOULD be similarly agnostic to the employed serialization format 1628 | and SHOULD clearly indicate this. If not, they MUST include an explanation on 1629 | which serialization formats are supported and on how to employ them correctly. 1630 | 1631 | Serialization formats make certain tradeoffs between usability, flexibility, 1632 | interoperability, and efficiency. Implementations should take these into 1633 | consideration when choosing a format. Some examples of possible formats are 1634 | JSON, CBOR, CSV, protocol buffers, flatbuffers, etc. which each have their own 1635 | characteristics. For instance, a textual format like JSON can be more flexible 1636 | than a binary format but more verbose, typically making it less efficient than a 1637 | binary format. A plaintext readable (yet relatively large) format like JSON is 1638 | potentially more usable for users operating on the logs directly, while a more 1639 | optimized yet restricted format can better suit the constraints of a large scale 1640 | operation. A custom or restricted format could be more efficient for analysis 1641 | with custom tooling but might not be interoperable with general-purpose qlog 1642 | tools. 1643 | 1644 | Considering these tradeoffs, JSON-based serialization formats provide features 1645 | that make them a good starting point for qlog flexibility and interoperability. 1646 | For these reasons, JSON is a recommended default and expanded considerations are 1647 | given to how to map qlog to JSON ({{format-json}}, and its streaming counterpart 1648 | JSON Text Sequences ({{format-json-seq}}. {{json-interop}} presents 1649 | interoperability considerations for both formats, and {{optimizations}} presents 1650 | potential optimizations. 1651 | 1652 | Serialization formats require appropriate deserializers/parsers. The 1653 | "serialization_format" field ({{abstract-logfile}}) is used to indicate the 1654 | chosen serialization format. 1655 | 1656 | ## qlog to JSON mapping {#format-json} 1657 | 1658 | As described in {{qlog-file-schema}}, JSON is the default qlog serialization. 1659 | When mapping qlog to normal JSON, QlogFile ({{qlog-file-def}}) is used. The 1660 | Media Type is "application/qlog+json" per {{!RFC6839}}. The file 1661 | extension/suffix SHOULD be ".qlog". 1662 | 1663 | In accordance with {{Section 8.1 of !RFC8259}}, JSON files are required to use 1664 | UTF-8 both for the file itself and the string values it contains. In addition, 1665 | all qlog field names MUST be lowercase when serialized to JSON. 1666 | 1667 | In order to serialize CDDL-based qlog event and data structure 1668 | definitions to JSON, the official CDDL-to-JSON mapping defined in 1669 | {{Appendix E of CDDL}} SHOULD be employed. 1670 | 1671 | ## qlog to JSON Text Sequences mapping {#format-json-seq} 1672 | 1673 | One of the downsides of using normal JSON is that it is inherently a 1674 | non-streamable format. A qlog serializer could work around this by opening a 1675 | file, writing the required opening data, streaming qlog events by appending 1676 | them, and then finalizing the log by appending appropriate closing tags e.g., 1677 | "]}]}". However, failure to append closing tags, could lead to problems because 1678 | most JSON parsers will fail if a document is malformed. Some streaming JSON 1679 | parsers are able to handle missing closing tags, however they are not widely 1680 | deployed in popular environments (e.g., Web browsers) 1681 | 1682 | To overcome the issues related to JSON streaming, a qlog mapping to a streamable 1683 | JSON format called JSON Text Sequences (JSON-SEQ) ({{!RFC7464}}) is provided. 1684 | 1685 | JSON Text Sequences are very similar to JSON, except that objects are 1686 | serialized as individual records, each prefixed by an ASCII Record Separator 1687 | (\, 0x1E), and each ending with an ASCII Line Feed character (\n, 0x0A). Note 1688 | that each record can also contain any amount of newlines in its body, as long as 1689 | it ends with a newline character before the next \ character. 1690 | 1691 | In order to leverage the streaming capability, each qlog event is serialized and 1692 | interpreted as an individual JSON Text Sequence record, that is appended as a 1693 | new object to the back of an event stream or log file. Put differently, unlike 1694 | default JSON, it does not require a document to be wrapped as a full object with 1695 | "{ ... }" or "\[... \]". 1696 | 1697 | This alternative record streaming approach cannot be accommodated by QlogFile 1698 | ({{qlog-file-def}}). Instead, QlogFileSeq is defined in {{qlog-file-seq-def}}, 1699 | which notably includes only a single trace (TraceSeq) and omits an explicit 1700 | "events" array. An example is provided in {{json-seq-ex}}. The "group_id" field 1701 | can still be used on a per-event basis to include events from conceptually 1702 | different sources in a single JSON-SEQ qlog file. 1703 | 1704 | When mapping qlog to JSON-SEQ, the Media Type is "application/qlog+json-seq" per 1705 | {{!RFC8091}}. The file extension/suffix SHOULD be ".sqlog" (for "streaming" 1706 | qlog). 1707 | 1708 | While not specifically required by the JSON-SEQ specification, all qlog field 1709 | names MUST be lowercase when serialized to JSON-SEQ. 1710 | 1711 | In order to serialize all other CDDL-based qlog event and data structure 1712 | definitions to JSON-SEQ, the official CDDL-to-JSON mapping defined in 1713 | {{Appendix E of CDDL}} SHOULD be employed. 1714 | 1715 | 1716 | ### Supporting JSON Text Sequences in tooling 1717 | 1718 | Note that JSON Text Sequences are not supported in most default programming 1719 | environments (unlike normal JSON). However, several custom JSON-SEQ parsing 1720 | libraries exist in most programming languages that can be used and the format is 1721 | easy enough to parse with existing implementations (i.e., by splitting the file 1722 | into its component records and feeding them to a normal JSON parser individually, 1723 | as each record by itself is a valid JSON object). 1724 | 1725 | ## JSON Interoperability {#json-interop} 1726 | 1727 | Some JSON implementations have issues with the full JSON format, especially those 1728 | integrated within a JavaScript environment (e.g., Web browsers, NodeJS). I-JSON 1729 | (Internet-JSON) is a subset of JSON for such environments; see 1730 | {{!I-JSON=RFC7493}}. One of the key limitations of JavaScript, and thus I-JSON, 1731 | is that it cannot represent full 64-bit integers in standard operating mode 1732 | (i.e., without using BigInt extensions), instead being limited to the range 1733 | -(253)+1 to (253)-1. 1734 | 1735 | To accommodate such constraints in CDDL, {{Appendix E of CDDL}} recommends 1736 | defining new CDDL types for int64 and uint64 that limit their values to the 1737 | restricted 64-bit integer range. However, some of the protocols that qlog is 1738 | intended to support (e.g., QUIC, HTTP/3), can use the full range of uint64 1739 | values. 1740 | 1741 | As such, to support situations where I-JSON is in use, seralizers MAY encode 1742 | uint64 values using JSON strings. qlog parsers, therefore, SHOULD support 1743 | parsing of uint64 values from JSON strings or JSON numbers unless there is out-of-band 1744 | information indicating that neither the serializer nor parser are constrained by 1745 | I-JSON. 1746 | 1747 | ## Truncated values {#truncated-values} 1748 | 1749 | For some use cases (e.g., limiting file size, privacy), it can be 1750 | necessary not to log a full raw blob (using the `hexstring` type) but 1751 | instead a truncated value. For example, one might only store the first 100 bytes of an 1752 | HTTP response body to be able to discern which file it actually 1753 | contained. In these cases, the original byte-size length cannot be 1754 | obtained from the serialized value directly. 1755 | 1756 | As such, all qlog schema definitions SHOULD include a separate, 1757 | length-indicating field for all fields of type `hexstring` they specify, 1758 | see for example {{raw-info}}. This not only ensures the original length 1759 | can always be retrieved, but also allows the omission of any raw value 1760 | bytes of the field completely (e.g., out of privacy or security 1761 | considerations). 1762 | 1763 | To reduce overhead however and in the case the full raw value is logged, 1764 | the extra length-indicating field can be left out. As such, tools MUST 1765 | be able to deal with this situation and derive the length of the field 1766 | from the raw value if no separate length-indicating field is present. 1767 | The main possible permutations are shown by example in 1768 | {{truncated-values-ex}}. 1769 | 1770 | ~~~~~~~~ 1771 | // both the content's value and its length are present 1772 | // (length is redundant) 1773 | { 1774 | "content_length": 5, 1775 | "content": "051428abff" 1776 | } 1777 | 1778 | // only the content value is present, indicating it 1779 | // represents the content's full value. The byte 1780 | // length is obtained by calculating content.length / 2 1781 | { 1782 | "content": "051428abff" 1783 | } 1784 | 1785 | // only the length is present, meaning the value 1786 | // was omitted 1787 | { 1788 | "content_length": 5, 1789 | } 1790 | 1791 | // both value and length are present, but the lengths 1792 | // do not match: the value was truncated to 1793 | // the first three bytes. 1794 | { 1795 | "content_length": 5, 1796 | "content": "051428" 1797 | } 1798 | ~~~~~~~~ 1799 | {: #truncated-values-ex title="Example for serializing truncated 1800 | hexstrings"} 1801 | 1802 | ## Optimization of serialized data {#optimizations} 1803 | 1804 | Both the JSON and JSON-SEQ formatting options described above are serviceable in 1805 | general small to medium scale (debugging) setups. However, these approaches tend 1806 | to be relatively verbose, leading to larger file sizes. Additionally, generalized 1807 | JSON(-SEQ) (de)serialization performance is typically (slightly) lower than that 1808 | of more optimized and predictable formats. Both aspects present challenges to 1809 | large scale setups, though they may still be practical to deploy; see [ANRW-2020]. 1810 | JSON and JSON-SEQ compress very well using commonly-available algorithms such as 1811 | GZIP or Brotli. 1812 | 1813 | During the development of qlog, a multitude of alternative formatting 1814 | and optimization options were assessed and the results are [summarized on the qlog 1815 | github 1816 | repository](https://github.com/quiclog/internet-drafts/issues/30#issuecomment-617675097). 1817 | 1818 | Formal definition of additional qlog formats or encodings that use the 1819 | optimization techniques described here, or any other optimization technique is 1820 | left to future activity that can apply the following guidelines. 1821 | 1822 | In order to help tools correctly parse and process serialized qlog, it is 1823 | RECOMMENDED that new formats also define suitable file extensions and media 1824 | types. This provides a clear signal and avoids the need to provide out-of-band 1825 | information or to rely on heuristic fallbacks; see {{tooling}}. 1826 | 1827 | # Methods of access and generation 1828 | 1829 | Different implementations will have different ways of generating and storing 1830 | qlogs. However, there is still value in defining a few default ways in which to 1831 | steer this generation and access of the results. 1832 | 1833 | ## Set file output destination via an environment variable 1834 | 1835 | To provide users control over where and how qlog files are created, two 1836 | environment variables are defined. The first, QLOGFILE, indicates a full path to where an 1837 | individual qlog file should be stored. This path MUST include the full file 1838 | extension. The second, QLOGDIR, sets a general directory path in which qlog files 1839 | should be placed. This path MUST include the directory separator character at the 1840 | end. 1841 | 1842 | In general, QLOGDIR should be preferred over QLOGFILE if an endpoint is prone to 1843 | generate multiple qlog files. This can for example be the case for a QUIC server 1844 | implementation that logs each QUIC connection in a separate qlog file. An 1845 | alternative that uses QLOGFILE would be a QUIC server that logs all connections in 1846 | a single file and uses the "group_id" field ({{group-ids}}) to allow post-hoc 1847 | separation of events. 1848 | 1849 | Implementations SHOULD provide support for QLOGDIR and MAY provide support for 1850 | QLOGFILE. 1851 | 1852 | When using QLOGDIR, it is up to the implementation to choose an appropriate naming 1853 | scheme for the qlog files themselves. The chosen scheme will typically depend on 1854 | the context or protocols used. For example, for QUIC, it is recommended to use the 1855 | Original Destination Connection ID (ODCID), followed by the vantage point type of 1856 | the logging endpoint. Examples of all options for QUIC are shown in 1857 | {{qlogdir-example}}. 1858 | 1859 | ~~~~~~~~ 1860 | Command: QLOGFILE=/srv/qlogs/client.qlog quicclientbinary 1861 | 1862 | Should result in the the quicclientbinary executable logging a 1863 | single qlog file named client.qlog in the /srv/qlogs directory. 1864 | This is for example useful in tests when the client sets up 1865 | just a single connection and then exits. 1866 | 1867 | Command: QLOGDIR=/srv/qlogs/ quicserverbinary 1868 | 1869 | Should result in the quicserverbinary executable generating 1870 | several logs files, one for each QUIC connection. 1871 | Given two QUIC connections, with ODCID values "abcde" and 1872 | "12345" respectively, this would result in two files: 1873 | /srv/qlogs/abcde_server.qlog 1874 | /srv/qlogs/12345_server.qlog 1875 | 1876 | Command: QLOGFILE=/srv/qlogs/server.qlog quicserverbinary 1877 | 1878 | Should result in the the quicserverbinary executable logging 1879 | a single qlog file named server.qlog in the /srv/qlogs directory. 1880 | Given that the server handled two QUIC connections before it was 1881 | shut down, with ODCID values "abcde" and "12345" respectively, 1882 | this would result in event instances in the qlog file being 1883 | tagged with the "group_id" field with values "abcde" and "12345". 1884 | ~~~~~~~~ 1885 | {: #qlogdir-example title="Environment variable examples for a QUIC implementation"} 1886 | 1887 | # Tooling requirements {#tooling} 1888 | 1889 | Tools ingestion qlog MUST indicate which qlog version(s), qlog format(s), qlog 1890 | file and event schema(s), compression methods and potentially other input file 1891 | formats (for example .pcap) they support. Tools SHOULD at least support .qlog 1892 | files in the default JSON format ({{format-json}}). Additionally, they SHOULD 1893 | indicate exactly which values for and properties of the name 1894 | (namespace:event_type) and data fields they look for to execute their logic. 1895 | Tools SHOULD perform a (high-level) check if an input qlog file adheres to the 1896 | expected qlog file and event schemas. If a tool determines a qlog file does not 1897 | contain enough supported information to correctly execute the tool's logic, it 1898 | SHOULD generate a clear error message to this effect. 1899 | 1900 | Tools MUST NOT produce breaking errors for any field names and/or values in the 1901 | qlog format that they do not recognize. Tools SHOULD indicate even unknown event 1902 | occurrences within their context (e.g., marking unknown events on a timeline for 1903 | manual interpretation by the user). 1904 | 1905 | Tool authors should be aware that, depending on the logging implementation, some 1906 | events will not always be present in all traces. For example, using a circular 1907 | logging buffer of a fixed size, it could be that the earliest events (e.g., 1908 | connection setup events) are later overwritten by "newer" events. Alternatively, 1909 | some events can be intentionally omitted out of privacy or file size 1910 | considerations. Tool authors are encouraged to make their tools robust enough to 1911 | still provide adequate output for incomplete logs. 1912 | 1913 | # Security and privacy considerations {#privacy} 1914 | 1915 | Protocols such as TLS {{?RFC8446}} and QUIC {{?RFC9000}} offer secure protection 1916 | for the wire image {{?RFC8546}}. Logging can reveal aspects of the wire image 1917 | that would ordinarily be protected, creating tension between observability, 1918 | security and privacy, especially if data can be correlated across data sources. 1919 | 1920 | qlog permits logging of a broad and detailed range of data. Operators and 1921 | implementers are responsible for deciding what data is logged to address their 1922 | requirements and constraints. As per {{?RFC6973}}, operators must be aware that 1923 | data could be compromised, risking the privacy of all participants. Where 1924 | entities expect protocol features to ensure data privacy, logging might 1925 | unknowingly be subject to broader privacy risks, undermining their ability to 1926 | assess or respond effectively. 1927 | 1928 | ## Data at risk 1929 | 1930 | qlog operators and implementers need to consider security and privacy risks when 1931 | handling qlog data, including logging, storage, usage, and more. The 1932 | considerations presented in this section may pose varying risks depending on the 1933 | the data itself or its handling. 1934 | 1935 | The following is a non-exhaustive list of example data types that could contain 1936 | sensitive information that might allow identification or correlation of 1937 | individual connections, endpoints, users or sessions across qlog or other data 1938 | sources (e.g., captures of encrypted packets): 1939 | 1940 | * IP addresses and transport protocol port numbers. 1941 | 1942 | * Session, Connection, or User identifiers e.g., QUIC Connection IDs {{Section 1943 | 9.5 of !RFC9000}}). 1944 | 1945 | * System-level information e.g., CPU, process, or thread identifiers. 1946 | 1947 | * Stored State e.g., QUIC address validation and retry tokens, TLS session 1948 | tickets, and HTTP cookies. 1949 | 1950 | * TLS decryption keys, passwords, and HTTP-level API access or authorization tokens. 1951 | 1952 | * High-resolution event timestamps or inter-event timings, event counts, packet 1953 | sizes, and frame sizes. 1954 | 1955 | * Full or partial raw packet and frame payloads that are encrypted. 1956 | 1957 | * Full or partial raw packet and frame payloads that are plaintext e.g., HTTP Field 1958 | values, HTTP response data, or TLS SNI field values. 1959 | 1960 | ## Operational implications and recommendations 1961 | 1962 | Operational considerations should focus on authorizing capture and access to logs. Logging of 1963 | Internet protocols using qlog can be equivalent to the ability to store or read plaintext 1964 | communications. Without a more detailed analysis, all of the security considerations of plaintext access apply. 1965 | 1966 | It is recommended that qlog capture is subject to access control and auditing. 1967 | These controls should support granular levels of information capture based on 1968 | role and permissions (e.g., capture of more-sensitive data requires higher 1969 | privileges). 1970 | 1971 | It is recommended that access to stored qlogs is subject to access control and 1972 | auditing. 1973 | 1974 | End users might not understand the implications of qlog to security or privacy, 1975 | and their environments might limit access control techniques. Implementations should 1976 | make enabling qlog conspicuous (e.g., requiring clear and explicit actions to 1977 | start a capture) and resistant to social engineering, automation, or drive-by 1978 | attacks; for example, isolation or sandboxing of capture from other activities 1979 | in the same process or component. 1980 | 1981 | It is recommended that data retention policies are defined for the storage of 1982 | qlog files. 1983 | 1984 | It is recommended that qlog files are encrypted in transit and at rest. 1985 | 1986 | ## Data minimization or anonymization 1987 | 1988 | Applying data minimization or anonymization techniques to qlog might help 1989 | address some security and privacy risks. However, removing or anonymizing data 1990 | without sufficient care might not enhance privacy or security and 1991 | could diminish the utility of qlog data. 1992 | 1993 | 1994 | Operators and implementers should balance the value of logged data with the 1995 | potential risks of voluntary or involuntary disclosure to trusted or untrusted 1996 | entities. Importantly, both the breadth and depth of the data needed to make it 1997 | useful, as well as the definition of entities depend greatly on the intended 1998 | use cases. For example, a research project might be tightly scoped, time bound, 1999 | and require participants to explicitly opt in to having their data collected 2000 | with the intention for this to be shared in a publication. Conversely, a server 2001 | administrator might desire to collect telemetry, from users whom they have no 2002 | relationship with, for continuing operational needs. 2003 | 2004 | The most extreme form of minimization or anonymization is deleting a field, 2005 | equivalent to not logging it. qlog implementations should offer fine-grained 2006 | control for this on a per-use-case or per-connection basis. 2007 | 2008 | Data can undergo anonymization, pseudonymization, permutation, truncation, 2009 | re-encryption, or aggregation; see {{Appendix B of !DNS-PRIVACY=RFC8932}} for 2010 | techniques, especially regarding IP addresses. However, operators should be 2011 | cautious because many anonymization methods have been shown to be insufficient to safeguard 2012 | user privacy or identity, particularly with large or easily correlated data sets. 2013 | 2014 | Operators should consider end user rights and preferences. Active user participation (as 2015 | indicated by {{!RFC6973}}) on a per-qlog basis is challenging but aligning qlog 2016 | capture, storage, and removal with existing user preference and privacy controls 2017 | is crucial. Operators should consider agressive approaches to deletion or 2018 | aggregation. 2019 | 2020 | The most sensitive data in qlog is typically contained in RawInfo type fields 2021 | (see {{raw-info}}). Therefore, qlog users should exercise caution and limit the 2022 | inclusion of such fields for all but the most stringent use cases. 2023 | 2024 | # IANA Considerations {#iana} 2025 | 2026 | IANA is requested to register a new entry in the "IETF URN Sub-namespace for 2027 | Registered Protocol Parameter Identifiers" registry ({{!RFC3553}})": 2028 | 2029 | Registered Parameter Identifier: 2030 | : qlog 2031 | 2032 | Reference: 2033 | : This Document 2034 | 2035 | IANA Registry Reference: 2036 | : [](https://www.iana.org/assignments/qlog){: brackets="angle"} 2037 | 2038 | IANA is requested to create the "qlog log file schema URIs" registry 2039 | at [](https://www.iana.org/assignments/qlog) for the purpose of registering 2040 | log file schema. It has the following format/template: 2041 | 2042 | Log File Schema URI: 2043 | : \[the log file schema identifier\] 2044 | 2045 | Description: 2046 | : \[a description of the log file schema\] 2047 | 2048 | Reference: 2049 | : \[to a specification defining the log file schema\] 2050 | 2051 | 2052 | This document furthermore adds the following two new entries to the "qlog log 2053 | file schema URIs" registry: 2054 | 2055 | | Log File Schema URI | Description | Reference | 2056 | | urn:ietf:params:qlog:file:contained | Concrete log file schema that can contain several traces from multiple vantage points. | {{qlog-file-schema}} | 2057 | | urn:ietf:params:qlog:file:sequential | Concrete log file schema containing a single trace, optimized for seqential read and write access. | {{qlog-file-seq-schema}} | 2058 | 2059 | IANA is requested to create the "qlog event schema URIs" registry 2060 | at [](https://www.iana.org/assignments/qlog) for the purpose of registering 2061 | event schema. It has the following format/template: 2062 | 2063 | Event schema URI: 2064 | : \[the event schema identifier\] 2065 | 2066 | Namespace: 2067 | : \[the identifier of the namespace that this event schema either defines or extends\] 2068 | 2069 | Event Types: 2070 | : \[a comma-separated list of concrete event types defined in the event schema\] 2071 | 2072 | Description: 2073 | : \[a description of the event schema\] 2074 | 2075 | Reference: 2076 | : \[to a specification defining the event schema definition\] 2077 | 2078 | This document furthermore adds the following two new entries to the "qlog event 2079 | schema URIs" registry: 2080 | 2081 | Event schema URI: 2082 | : urn:ietf:params:qlog:events:loglevel 2083 | 2084 | Namespace 2085 | : loglevel 2086 | 2087 | Event Types 2088 | : error,warning,info,debug,verbose 2089 | 2090 | Description: 2091 | : Well-known logging levels for free-form text. 2092 | 2093 | Reference: 2094 | : {{loglevel-events}} 2095 | 2096 | 2097 | Event schema URI: 2098 | : urn:ietf:params:qlog:events:simulation 2099 | 2100 | Namespace 2101 | : simulation 2102 | 2103 | Event Types 2104 | : scenario,marker 2105 | 2106 | Description: 2107 | : Events for simulation testing. 2108 | 2109 | Reference: 2110 | : {{sim-events}} 2111 | 2112 | --- back 2113 | 2114 | # Acknowledgements 2115 | {:numbered="false"} 2116 | 2117 | Much of the initial work by Robin Marx was done at the Hasselt and KU Leuven 2118 | Universities. 2119 | 2120 | Thanks to Jana Iyengar, Brian Trammell, Dmitri Tikhonov, Stephen Petrides, Jari 2121 | Arkko, Marcus Ihlar, Victor Vasiliev, Mirja Kühlewind, Jeremy Lainé, Kazu 2122 | Yamamoto, Christian Huitema, Hugo Landau, Will Hawkins, Mathis Engelbart and 2123 | Jonathan Lennox for their feedback and suggestions. 2124 | 2125 | # Change Log 2126 | {:numbered="false" removeinrfc="true"} 2127 | 2128 | 2129 | ## Since draft-ietf-quic-qlog-main-schema-10: 2130 | {:numbered="false"} 2131 | 2132 | * Multiple editorial changes 2133 | * Remove protocol_types and move event_schemas to Trace and TraceSeq (#449) 2134 | 2135 | ## Since draft-ietf-quic-qlog-main-schema-09: 2136 | {:numbered="false"} 2137 | 2138 | * Renamed `protocol_type` to `protocol_types` (#427) 2139 | * Moved Trigger section. Purely editorial (#430) 2140 | * Removed the concept of categories and updated extension and event schema logic 2141 | to match. Major change (#439) 2142 | * Reworked completely how we handle timestamps and clocks. Major change (#433) 2143 | 2144 | ## Since draft-ietf-quic-qlog-main-schema-08: 2145 | {:numbered="false"} 2146 | 2147 | * TODO (we forgot...) 2148 | 2149 | ## Since draft-ietf-quic-qlog-main-schema-07: 2150 | {:numbered="false"} 2151 | 2152 | * Added path and PathID (#336) 2153 | * Removed custom definition of uint64 type (#360, #388) 2154 | * ProtocolEventBody is now called ProtocolEventData (#352) 2155 | * Editorial changes (#364, #289, #353, #361, #362) 2156 | 2157 | ## Since draft-ietf-quic-qlog-main-schema-06: 2158 | {:numbered="false"} 2159 | 2160 | * Editorial reworking of the document (#331, #332) 2161 | * Updated IANA considerations section (#333) 2162 | 2163 | ## Since draft-ietf-quic-qlog-main-schema-05: 2164 | {:numbered="false"} 2165 | 2166 | * Updated qlog_version to 0.4 (due to breaking changes) (#314) 2167 | * Renamed 'transport' category to 'quic' (#302) 2168 | * Added 'system_info' field (#305) 2169 | * Removed 'summary' and 'configuration' fields (#308) 2170 | * Editorial and formatting changes (#298, #303, #304, #316, #320, #321, #322, #326, #328) 2171 | 2172 | ## Since draft-ietf-quic-qlog-main-schema-04: 2173 | {:numbered="false"} 2174 | 2175 | * Updated RawInfo definition and guidance (#243) 2176 | 2177 | ## Since draft-ietf-quic-qlog-main-schema-03: 2178 | {:numbered="false"} 2179 | 2180 | * Added security and privacy considerations discussion (#252) 2181 | 2182 | ## Since draft-ietf-quic-qlog-main-schema-02: 2183 | {:numbered="false"} 2184 | 2185 | * No changes - new draft to prevent expiration 2186 | 2187 | ## Since draft-ietf-quic-qlog-main-schema-01: 2188 | {:numbered="false"} 2189 | 2190 | * Change the data definition language from TypeScript to CDDL (#143) 2191 | 2192 | ## Since draft-ietf-quic-qlog-main-schema-00: 2193 | {:numbered="false"} 2194 | 2195 | * Changed the streaming serialization format from NDJSON to JSON Text Sequences 2196 | (#172) 2197 | * Added Media Type definitions for various qlog formats (#158) 2198 | * Changed to semantic versioning 2199 | 2200 | ## Since draft-marx-qlog-main-schema-draft-02: 2201 | {:numbered="false"} 2202 | 2203 | * These changes were done in preparation of the adoption of the drafts by the QUIC 2204 | working group (#137) 2205 | * Moved RawInfo, Importance, Generic events and Simulation events to this document. 2206 | * Added basic event definition guidelines 2207 | * Made protocol_type an array instead of a string (#146) 2208 | 2209 | ## Since draft-marx-qlog-main-schema-01: 2210 | {:numbered="false"} 2211 | 2212 | * Decoupled qlog from the JSON format and described a mapping instead (#89) 2213 | * Data types are now specified in this document and proper definitions for 2214 | fields were added in this format 2215 | * 64-bit numbers can now be either strings or numbers, with a preference for 2216 | numbers (#10) 2217 | * binary blobs are now logged as lowercase hex strings (#39, #36) 2218 | * added guidance to add length-specifiers for binary blobs (#102) 2219 | * Removed "time_units" from Configuration. All times are now in ms instead (#95) 2220 | * Removed the "event_fields" setup for a more straightforward JSON format 2221 | (#101,#89) 2222 | * Added a streaming option using the NDJSON format (#109,#2,#106) 2223 | * Described optional optimization options for implementers (#30) 2224 | * Added QLOGDIR and QLOGFILE environment variables, clarified the .well-known URL 2225 | usage (#26,#33,#51) 2226 | * Overall tightened up the text and added more examples 2227 | 2228 | ## Since draft-marx-qlog-main-schema-00: 2229 | {:numbered="false"} 2230 | 2231 | * All field names are now lowercase (e.g., category instead of CATEGORY) 2232 | * Triggers are now properties on the "data" field value, instead of separate field 2233 | types (#23) 2234 | * group_ids in common_fields is now just also group_id 2235 | 2236 | --------------------------------------------------------------------------------