]> git.feebdaed.xyz Git - 0xmirror/quic-go.git/commitdiff
qlogwriter: add support for event_schemas in the trace header (#5361)
authorMarten Seemann <martenseemann@gmail.com>
Thu, 9 Oct 2025 04:07:23 +0000 (12:07 +0800)
committerGitHub <noreply@github.com>
Thu, 9 Oct 2025 04:07:23 +0000 (06:07 +0200)
integrationtests/tools/qlog.go
interop/utils/logging.go
qlog/benchmark_test.go
qlog/qlog_dir.go
qlogwriter/trace.go
qlogwriter/trace_test.go
qlogwriter/writer.go

index 8527ffe7d3f7b7ed71f03a71784ff40174b9d0dd..19917f25e9bb95949ada28763cb33d010a9eda93 100644 (file)
@@ -11,6 +11,7 @@ import (
 
        "github.com/quic-go/quic-go"
        "github.com/quic-go/quic-go/internal/utils"
+       "github.com/quic-go/quic-go/qlog"
        "github.com/quic-go/quic-go/qlogwriter"
 )
 
@@ -41,7 +42,12 @@ func NewQlogConnectionTracer(logger io.Writer) func(ctx context.Context, isClien
                        log.Fatalf("failed to create qlog file: %s", err)
                        return nil
                }
-               fileSeq := qlogwriter.NewConnectionFileSeq(utils.NewBufferedWriteCloser(bufio.NewWriter(f), f), isClient, connID)
+               fileSeq := qlogwriter.NewConnectionFileSeq(
+                       utils.NewBufferedWriteCloser(bufio.NewWriter(f), f),
+                       isClient,
+                       connID,
+                       []string{qlog.EventSchema},
+               )
                go fileSeq.Run()
                return fileSeq
        }
index 405a93a35c6ddc9be6a2ad346b2e0d341fe22455..53bac8d2d8376136e5342c26dbe9c40d57c59d9d 100644 (file)
@@ -11,6 +11,7 @@ import (
 
        "github.com/quic-go/quic-go"
        "github.com/quic-go/quic-go/internal/utils"
+       "github.com/quic-go/quic-go/qlog"
        "github.com/quic-go/quic-go/qlogwriter"
 )
 
@@ -45,7 +46,12 @@ func NewQLOGConnectionTracer(_ context.Context, isClient bool, connID quic.Conne
                return nil
        }
        log.Printf("Created qlog file: %s\n", path)
-       fileSeq := qlogwriter.NewConnectionFileSeq(utils.NewBufferedWriteCloser(bufio.NewWriter(f), f), isClient, connID)
+       fileSeq := qlogwriter.NewConnectionFileSeq(
+               utils.NewBufferedWriteCloser(bufio.NewWriter(f), f),
+               isClient,
+               connID,
+               []string{qlog.EventSchema},
+       )
        go fileSeq.Run()
        return fileSeq
 }
index a16f6bee01972c09aada17822d3c49156e26e17c..caf40b41738025374a70c5ed63f0870ffbdefd7c 100644 (file)
@@ -28,6 +28,7 @@ func BenchmarkConnectionTracing(b *testing.B) {
                nopWriteCloser(io.Discard),
                false,
                protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}),
+               []string{EventSchema},
        )
        go trace.Run()
        tracer := trace.AddProducer()
index 12f0093771fc27659369dad29dae72fb7dfb0c03..c014a1c3f1b0d253bc999973ff0b1debd7718299 100644 (file)
@@ -12,6 +12,9 @@ import (
        "github.com/quic-go/quic-go/qlogwriter"
 )
 
+// EventSchema is the qlog event schema for QUIC
+const EventSchema = "urn:ietf:params:qlog:events:quic-12"
+
 // DefaultConnectionTracer creates a qlog file in the qlog directory specified by the QLOGDIR environment variable.
 // File names are <odcid>_<perspective>.sqlog.
 // Returns nil if QLOGDIR is not set.
@@ -35,7 +38,12 @@ func DefaultConnectionTracer(_ context.Context, isClient bool, connID Connection
                log.Printf("Failed to create qlog file %s: %s", path, err.Error())
                return nil
        }
-       fileSeq := qlogwriter.NewConnectionFileSeq(utils.NewBufferedWriteCloser(bufio.NewWriter(f), f), isClient, connID)
+       fileSeq := qlogwriter.NewConnectionFileSeq(
+               utils.NewBufferedWriteCloser(bufio.NewWriter(f), f),
+               isClient,
+               connID,
+               []string{EventSchema},
+       )
        go fileSeq.Run()
        return fileSeq
 }
index cba8b29880848c927b3acc917d0c3bf074c9d669..2b09bc788009562d7381b7f08a9d43d6c7a794c2 100644 (file)
@@ -42,6 +42,7 @@ type traceHeader struct {
        VantagePointType string
        GroupID          *ConnectionID
        ReferenceTime    time.Time
+       EventSchemas     []string
 }
 
 func (l traceHeader) Encode(enc *jsontext.Encoder) error {
@@ -59,6 +60,15 @@ func (l traceHeader) Encode(enc *jsontext.Encoder) error {
        h.WriteToken(jsontext.String("trace"))
        // trace
        h.WriteToken(jsontext.BeginObject)
+       if len(l.EventSchemas) > 0 {
+               h.WriteToken(jsontext.String("event_schemas"))
+               h.WriteToken(jsontext.BeginArray)
+               for _, schema := range l.EventSchemas {
+                       h.WriteToken(jsontext.String(schema))
+               }
+               h.WriteToken(jsontext.EndArray)
+       }
+
        h.WriteToken(jsontext.String("vantage_point"))
        // -- vantage_point
        h.WriteToken(jsontext.BeginObject)
index b55e141f0873f48332e1cc85c453e5131146e366..69d018b1cfbd470183245afb89b72ddd13f763a6 100644 (file)
@@ -48,7 +48,7 @@ func TestTraceMetadata(t *testing.T) {
                producer := trace.AddProducer()
                producer.Close()
 
-               testTraceMetadata(t, buf, "transport", "")
+               testTraceMetadata(t, buf, "transport", "", []string{})
        })
 
        t.Run("connection trace", func(t *testing.T) {
@@ -57,16 +57,27 @@ func TestTraceMetadata(t *testing.T) {
                        nopWriteCloser(buf),
                        false,
                        protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}),
+                       []string{"urn:ietf:params:qlog:events:foo", "urn:ietf:params:qlog:events:bar"},
                )
                go trace.Run()
                producer := trace.AddProducer()
                producer.Close()
 
-               testTraceMetadata(t, buf, "server", "deadbeef")
+               testTraceMetadata(t,
+                       buf,
+                       "server",
+                       "deadbeef",
+                       []string{"urn:ietf:params:qlog:events:foo", "urn:ietf:params:qlog:events:bar"},
+               )
        })
 }
 
-func testTraceMetadata(t *testing.T, buf *bytes.Buffer, expectedVantagePoint, expectedGroupID string) {
+func testTraceMetadata(t *testing.T,
+       buf *bytes.Buffer,
+       expectedVantagePoint,
+       expectedGroupID string,
+       expectedEventSchemas []string,
+) {
        var m map[string]any
        require.NoError(t, unmarshal(buf.Bytes(), &m))
        require.Equal(t, "0.3", m["qlog_version"])
@@ -95,4 +106,13 @@ func testTraceMetadata(t *testing.T, buf *bytes.Buffer, expectedVantagePoint, ex
        require.Contains(t, tr, "vantage_point")
        vantagePoint := tr["vantage_point"].(map[string]any)
        require.Equal(t, expectedVantagePoint, vantagePoint["type"])
+       if len(expectedEventSchemas) > 0 {
+               require.Contains(t, tr, "event_schemas")
+               eventSchemas := tr["event_schemas"].([]any)
+               for i, schema := range eventSchemas {
+                       require.Equal(t, expectedEventSchemas[i], schema)
+               }
+       } else {
+               require.NotContains(t, tr, "event_schemas")
+       }
 }
index 19cfde128a2e71ab9723db4933a89d8bf39d7a3f..fc4c6682d7eeba0546ded87db9fa604a8bbeb3e7 100644 (file)
@@ -56,19 +56,19 @@ var _ Trace = &FileSeq{}
 
 // NewFileSeq creates a new JSON-SEQ qlog trace to log transport events.
 func NewFileSeq(w io.WriteCloser) *FileSeq {
-       return newFileSeq(w, "transport", nil)
+       return newFileSeq(w, "transport", nil, nil)
 }
 
 // NewConnectionFileSeq creates a new qlog trace to log connection events.
-func NewConnectionFileSeq(w io.WriteCloser, isClient bool, odcid ConnectionID) *FileSeq {
+func NewConnectionFileSeq(w io.WriteCloser, isClient bool, odcid ConnectionID, eventSchemas []string) *FileSeq {
        pers := "server"
        if isClient {
                pers = "client"
        }
-       return newFileSeq(w, pers, &odcid)
+       return newFileSeq(w, pers, &odcid, eventSchemas)
 }
 
-func newFileSeq(w io.WriteCloser, pers string, odcid *ConnectionID) *FileSeq {
+func newFileSeq(w io.WriteCloser, pers string, odcid *ConnectionID, eventSchemas []string) *FileSeq {
        now := time.Now()
        buf := &bytes.Buffer{}
        enc := jsontext.NewEncoder(buf)
@@ -79,6 +79,7 @@ func newFileSeq(w io.WriteCloser, pers string, odcid *ConnectionID) *FileSeq {
                VantagePointType: pers,
                GroupID:          odcid,
                ReferenceTime:    now,
+               EventSchemas:     eventSchemas,
        }).Encode(enc); err != nil {
                panic(fmt.Sprintf("qlog encoding into a bytes.Buffer failed: %s", err))
        }