implement marshalling of events

This commit is contained in:
Marten Seemann
2020-01-21 11:02:40 +07:00
parent 572ef44cf2
commit e6d55ac467
4 changed files with 135 additions and 0 deletions

41
qlog/event.go Normal file
View File

@@ -0,0 +1,41 @@
package qlog
import (
"time"
"github.com/francoispqt/gojay"
)
var eventFields = [4]string{"time", "category", "event", "data"}
type events []event
var _ gojay.MarshalerJSONArray = events{}
func (e events) IsNil() bool { return e == nil }
func (e events) MarshalJSONArray(enc *gojay.Encoder) {
for _, ev := range e {
enc.Array(ev)
}
}
type eventDetails interface {
Category() category
Name() string
gojay.MarshalerJSONObject
}
type event struct {
Time time.Time
eventDetails
}
var _ gojay.MarshalerJSONArray = event{}
func (e event) IsNil() bool { return false }
func (e event) MarshalJSONArray(enc *gojay.Encoder) {
enc.Float64(float64(e.Time.UnixNano()) / 1e6)
enc.String(e.Category().String())
enc.String(e.Name())
enc.Object(e.eventDetails)
}

54
qlog/event_test.go Normal file
View File

@@ -0,0 +1,54 @@
package qlog
import (
"bytes"
"encoding/json"
"time"
"github.com/francoispqt/gojay"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type mevent struct{}
var _ eventDetails = mevent{}
func (mevent) Category() category { return categoryConnectivity }
func (mevent) Name() string { return "mevent" }
func (mevent) IsNil() bool { return false }
func (mevent) MarshalJSONObject(enc *gojay.Encoder) { enc.StringKey("event", "details") }
var _ = Describe("Events", func() {
It("marshals the fields before the event details", func() {
now := time.Now()
buf := &bytes.Buffer{}
enc := gojay.NewEncoder(buf)
Expect(enc.Encode(event{
Time: now,
eventDetails: mevent{},
})).To(Succeed())
var decoded []interface{}
Expect(json.Unmarshal(buf.Bytes(), &decoded)).To(Succeed())
Expect(decoded).To(HaveLen(4))
// 1st field
Expect(eventFields[0]).To(Equal("time"))
Expect(time.Unix(0, int64(1e6*decoded[0].(float64)))).To(BeTemporally("~", now, 2*time.Microsecond))
// 2nd field
Expect(eventFields[1]).To(Equal("category"))
Expect(decoded[1].(string)).To(Equal(categoryConnectivity.String()))
// 3rd field
Expect(eventFields[2]).To(Equal("event"))
Expect(decoded[2].(string)).To(Equal("mevent"))
// 4th field
Expect(eventFields[3]).To(Equal("data"))
Expect(decoded[3].(map[string]interface{})["event"]).To(Equal("details"))
})
})

View File

@@ -35,3 +35,28 @@ type connectionID protocol.ConnectionID
func (c connectionID) String() string {
return fmt.Sprintf("%x", []byte(c))
}
// category is the qlog event category.
type category uint8
const (
categoryConnectivity category = iota
categoryTransport
categorySecurity
categoryRecovery
)
func (c category) String() string {
switch c {
case categoryConnectivity:
return "connectivity"
case categoryTransport:
return "transport"
case categorySecurity:
return "security"
case categoryRecovery:
return "recovery"
default:
panic("unknown category")
}
}

15
qlog/types_test.go Normal file
View File

@@ -0,0 +1,15 @@
package qlog
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Types", func() {
It("has a string representation for the category", func() {
Expect(categoryConnectivity.String()).To(Equal("connectivity"))
Expect(categoryTransport.String()).To(Equal("transport"))
Expect(categoryRecovery.String()).To(Equal("recovery"))
Expect(categorySecurity.String()).To(Equal("security"))
})
})