"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"
)
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
}
"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"
)
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
}
nopWriteCloser(io.Discard),
false,
protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}),
+ []string{EventSchema},
)
go trace.Run()
tracer := trace.AddProducer()
"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.
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
}
VantagePointType string
GroupID *ConnectionID
ReferenceTime time.Time
+ EventSchemas []string
}
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)
producer := trace.AddProducer()
producer.Close()
- testTraceMetadata(t, buf, "transport", "")
+ testTraceMetadata(t, buf, "transport", "", []string{})
})
t.Run("connection trace", func(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"])
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")
+ }
}
// 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)
VantagePointType: pers,
GroupID: odcid,
ReferenceTime: now,
+ EventSchemas: eventSchemas,
}).Encode(enc); err != nil {
panic(fmt.Sprintf("qlog encoding into a bytes.Buffer failed: %s", err))
}