Skip to content

Commit

Permalink
Upgrade modeljson ints to int64 if their proto uses int64 (#122)
Browse files Browse the repository at this point in the history
* introduce a nullable.Int64

* upgrade modeljson int to int64 if their proto uses int64

* remove transforms from int64 to int

* handle int64 in generator

* populate int64
  • Loading branch information
dmathieu authored Jul 26, 2023
1 parent 4939b2f commit ce52c31
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 11 deletions.
2 changes: 1 addition & 1 deletion input/elasticapm/internal/modeldecoder/generator/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ if !val.IsSet() {
switch f.Type().String() {
case nullableTypeString:
validation = generateNullableStringValidation
case nullableTypeInt:
case nullableTypeInt, nullableTypeInt64:
validation = generateNullableIntValidation
case nullableTypeFloat64:
// right now we can reuse the validation rules for int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (g *JSONSchemaGenerator) generate(st structType, key string, prop *property
err = generateJSONPropertyJSONNumber(&info, prop, &childProp)
case nullableTypeHTTPHeader:
err = generateJSONPropertyHTTPHeader(&info, prop, &childProp)
case nullableTypeInt, nullableTypeTimeMicrosUnix:
case nullableTypeInt, nullableTypeInt64, nullableTypeTimeMicrosUnix:
err = generateJSONPropertyInteger(&info, prop, &childProp)
case nullableTypeInterface:
err = generateJSONPropertyInterface(&info, prop, &childProp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
nullableTypeFloat64 = fmt.Sprintf("%s.Float64", typPath)
nullableTypeHTTPHeader = fmt.Sprintf("%s.HTTPHeader", typPath)
nullableTypeInt = fmt.Sprintf("%s.Int", typPath)
nullableTypeInt64 = fmt.Sprintf("%s.Int64", typPath)
nullableTypeInterface = fmt.Sprintf("%s.Interface", typPath)
nullableTypeString = fmt.Sprintf("%s.String", typPath)
nullableTypeTimeMicrosUnix = fmt.Sprintf("%s.TimeMicrosUnix", typPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func validateJSONTag(flatTag, nestedTag string) bool {

func getFlatFieldType(f structField) (string, error) {
switch typ := f.Type().String(); typ {
case nullableTypeInt:
case nullableTypeInt, nullableTypeInt64:
return "json.Number", nil
case nullableTypeString:
return "string", nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ func SetStructValues(in interface{}, values *Values, opts ...SetStructValuesOpti
case nullable.Int:
v.Set(values.Int)
fieldVal = reflect.ValueOf(v)
case nullable.Int64:
v.Set(int64(values.Int))
fieldVal = reflect.ValueOf(v)
case nullable.Interface:
if strings.Contains(key, "port") {
v.Set(values.Int)
Expand Down
34 changes: 34 additions & 0 deletions input/elasticapm/internal/modeldecoder/nullable/nullable.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ func init() {
(*((*Int)(ptr))).isSet = true
}
})
jsoniter.RegisterTypeDecoderFunc("nullable.Int64", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NilValue:
iter.ReadNil()
default:
(*((*Int64)(ptr))).Val = iter.ReadInt64()
(*((*Int64)(ptr))).isSet = true
}
})
jsoniter.RegisterTypeDecoderFunc("nullable.Float64", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NilValue:
Expand Down Expand Up @@ -193,6 +202,31 @@ func (v *Int) Reset() {
v.isSet = false
}

// Int64 stores an int64 value and the
// information if the value has been set
type Int64 struct {
Val int64
isSet bool
}

// Set sets the value
func (v *Int64) Set(val int64) {
v.Val = val
v.isSet = true
}

// IsSet is true when decode was called
func (v *Int64) IsSet() bool {
return v.isSet
}

// Reset sets the Int64 to it's initial state
// where it is not set and has no value
func (v *Int64) Reset() {
v.Val = 0
v.isSet = false
}

// Float64 stores a float64 value and the
// information if the value has been set
type Float64 struct {
Expand Down
38 changes: 38 additions & 0 deletions input/elasticapm/internal/modeldecoder/nullable/nullable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
type testType struct {
S String `json:"s"`
I Int `json:"i"`
I64 Int64 `json:"i64"`
F Float64 `json:"f"`
B Bool `json:"b"`
V Interface `json:"v"`
Expand Down Expand Up @@ -114,6 +115,43 @@ func TestInt(t *testing.T) {
}
}

func TestInt64(t *testing.T) {
for _, tc := range []struct {
name string
input string

val int64
isSet, fail bool
}{
{name: "values", input: `{"i64":44}`, val: 44, isSet: true},
{name: "empty", input: `{"i64":0}`, isSet: true},
{name: "null", input: `{"i64":null}`, isSet: false},
{name: "missing", input: `{}`},
{name: "invalid", input: `{"i64":"1.0.1"}`, fail: true},
} {
t.Run(tc.name, func(t *testing.T) {
dec := json.NewDecoder(strings.NewReader(tc.input))
var testStruct testType
err := dec.Decode(&testStruct)
if tc.fail {
require.Error(t, err)
} else {
require.NoError(t, err)
assert.Equal(t, tc.isSet, testStruct.I64.IsSet())
assert.Equal(t, tc.val, testStruct.I64.Val)
}

testStruct.I64.Reset()
assert.False(t, testStruct.I64.IsSet())
assert.Empty(t, testStruct.I64.Val)

testStruct.I64.Set(55)
assert.True(t, testStruct.I64.IsSet())
assert.Equal(t, int64(55), testStruct.I64.Val)
})
}
}

func TestFloat64(t *testing.T) {
for _, tc := range []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion input/elasticapm/internal/modeldecoder/v2/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ type transactionUserExperience struct {

type longtaskMetrics struct {
// Count is the total number of of longtasks.
Count nullable.Int `json:"count" validate:"required,min=0"`
Count nullable.Int64 `json:"count" validate:"required,min=0"`
// Max longtask duration
Max nullable.Float64 `json:"max" validate:"required,min=0"`
// Sum of longtask durations
Expand Down
2 changes: 1 addition & 1 deletion model/internal/modeljson/marshal_fastjson.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion model/internal/modeljson/metricset.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (ms *MetricsetSample) MarshalFastJSON(w *fastjson.Writer) error {
}

type AggregatedDuration struct {
Count int
Count int64
Sum time.Duration
}

Expand Down
2 changes: 1 addition & 1 deletion model/internal/modeljson/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ package modeljson

type Session struct {
ID string `json:"id"`
Sequence int `json:"sequence,omitempty"`
Sequence int64 `json:"sequence,omitempty"`
}
2 changes: 1 addition & 1 deletion model/modelpb/apmevent.pb.json.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (e *APMEvent) MarshalFastJSON(w *fastjson.Writer) error {
if e.Session != nil {
doc.Session = &modeljson.Session{
ID: e.Session.Id,
Sequence: int(e.Session.Sequence),
Sequence: e.Session.Sequence,
}
}

Expand Down
4 changes: 2 additions & 2 deletions model/modelpb/span.pb.json.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (e *Span) toModelJSON(out *modeljson.Span) {
}
if e.SelfTime != nil {
out.SelfTime = modeljson.AggregatedDuration{
Count: int(e.SelfTime.Count),
Count: e.SelfTime.Count,
Sum: e.SelfTime.Sum.AsDuration(),
}
}
Expand All @@ -87,7 +87,7 @@ func (e *Span) toModelJSON(out *modeljson.Span) {
}
if e.DestinationService.ResponseTime != nil {
out.Destination.Service.ResponseTime = modeljson.AggregatedDuration{
Count: int(e.DestinationService.ResponseTime.Count),
Count: e.DestinationService.ResponseTime.Count,
Sum: e.DestinationService.ResponseTime.Sum.AsDuration(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion model/modelpb/transaction.pb.json.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (e *Transaction) toModelJSON(out *modeljson.Transaction, metricset bool) {

if dss.Duration != nil {
dssJson.Duration = modeljson.AggregatedDuration{
Count: int(dss.Duration.Count),
Count: dss.Duration.Count,
Sum: dss.Duration.Sum.AsDuration(),
}
}
Expand Down

0 comments on commit ce52c31

Please sign in to comment.