Skip to content

Commit e9df345

Browse files
authored
Fix validation of histograms and fields with object_type (#939)
1 parent c031a1d commit e9df345

File tree

6 files changed

+113
-9
lines changed

6 files changed

+113
-9
lines changed

internal/fields/model.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type FieldDefinition struct {
1818
Name string `yaml:"name"`
1919
Description string `yaml:"description"`
2020
Type string `yaml:"type"`
21+
ObjectType string `yaml:"object_type"`
2122
Value string `yaml:"value"` // The value to associate with a constant_keyword field.
2223
AllowedValues AllowedValues `yaml:"allowed_values"`
2324
ExpectedValues []string `yaml:"expected_values"`
@@ -41,6 +42,9 @@ func (orig *FieldDefinition) Update(fd FieldDefinition) {
4142
if fd.Type != "" {
4243
orig.Type = fd.Type
4344
}
45+
if fd.ObjectType != "" {
46+
orig.ObjectType = fd.ObjectType
47+
}
4448
if fd.Value != "" {
4549
orig.Value = fd.Value
4650
}

internal/fields/validate.go

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -350,14 +350,44 @@ func compareKeys(key string, def FieldDefinition, searchedKey string) bool {
350350
return true
351351
}
352352

353-
// Workaround for potential geo_point, as "lon" and "lat" fields are not present in field definitions.
354-
// Unfortunately we have to assume that imported field could be a geo_point (nasty workaround).
353+
// Workaround for potential subfields of certain types as geo_point or histogram.
355354
if len(searchedKey) > j {
356-
if def.Type == "geo_point" || def.External != "" {
357-
extraPart := searchedKey[j:]
358-
if extraPart == ".lon" || extraPart == ".lat" {
359-
return true
360-
}
355+
extraPart := searchedKey[j:]
356+
if validSubField(def, extraPart) {
357+
return true
358+
}
359+
}
360+
361+
return false
362+
}
363+
364+
// validSubField checks if the extra part that didn't match with any field definition,
365+
// matches with the possible sub field of complex fields like geo_point or histogram.
366+
func validSubField(def FieldDefinition, extraPart string) bool {
367+
fieldType := def.Type
368+
if def.Type == "object" && def.ObjectType != "" {
369+
fieldType = def.ObjectType
370+
}
371+
372+
subFields := []string{".lat", ".lon", ".values", ".counts"}
373+
perType := map[string][]string{
374+
"geo_point": subFields[0:2],
375+
"histogram": subFields[2:4],
376+
}
377+
378+
allowed, found := perType[fieldType]
379+
if !found {
380+
if def.External != "" {
381+
// An unresolved external field could be anything.
382+
allowed = subFields
383+
} else {
384+
return false
385+
}
386+
}
387+
388+
for _, a := range allowed {
389+
if a == extraPart {
390+
return true
361391
}
362392
}
363393

internal/fields/validate_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,12 +525,42 @@ func TestCompareKeys(t *testing.T) {
525525
searchedKey: "example.geo.lat",
526526
expected: true,
527527
},
528+
{
529+
key: "example.*",
530+
def: FieldDefinition{Type: "object", ObjectType: "geo_point"},
531+
searchedKey: "example.geo.lon",
532+
expected: true,
533+
},
528534
{
529535
key: "example.*",
530536
def: FieldDefinition{Type: "geo_point"},
531537
searchedKey: "example.geo.foo",
532538
expected: false,
533539
},
540+
{
541+
key: "example.histogram",
542+
def: FieldDefinition{Type: "histogram"},
543+
searchedKey: "example.histogram.counts",
544+
expected: true,
545+
},
546+
{
547+
key: "example.*",
548+
def: FieldDefinition{Type: "histogram"},
549+
searchedKey: "example.histogram.counts",
550+
expected: true,
551+
},
552+
{
553+
key: "example.*",
554+
def: FieldDefinition{Type: "histogram"},
555+
searchedKey: "example.histogram.values",
556+
expected: true,
557+
},
558+
{
559+
key: "example.*",
560+
def: FieldDefinition{Type: "histogram"},
561+
searchedKey: "example.histogram.foo",
562+
expected: false,
563+
},
534564
}
535565

536566
for _, c := range cases {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- name: service.status.*.histogram
2+
type: object
3+
object_type: histogram

test/packages/other/fields_tests/data_stream/first/sample_event.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,23 @@
44
"lon": "2.0"
55
},
66
"destination.geo.location.lat": 3.0,
7-
"destination.geo.location.lon": 4.0
7+
"destination.geo.location.lon": 4.0,
8+
"service.status.duration.histogram": {
9+
"counts": [
10+
8,
11+
17,
12+
8,
13+
7,
14+
6,
15+
2
16+
],
17+
"values": [
18+
0.1,
19+
0.25,
20+
0.35,
21+
0.4,
22+
0.45,
23+
0.5
24+
]
25+
}
826
}

test/packages/other/fields_tests/docs/README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,25 @@ An example event for `first` looks as following:
99
"lon": "2.0"
1010
},
1111
"destination.geo.location.lat": 3.0,
12-
"destination.geo.location.lon": 4.0
12+
"destination.geo.location.lon": 4.0,
13+
"service.status.duration.histogram": {
14+
"counts": [
15+
8,
16+
17,
17+
8,
18+
7,
19+
6,
20+
2
21+
],
22+
"values": [
23+
0.1,
24+
0.25,
25+
0.35,
26+
0.4,
27+
0.45,
28+
0.5
29+
]
30+
}
1331
}
1432
```
1533

@@ -22,4 +40,5 @@ An example event for `first` looks as following:
2240
| data_stream.namespace | Data stream namespace. | constant_keyword |
2341
| data_stream.type | Data stream type. | constant_keyword |
2442
| destination.geo.location | Longitude and latitude. | geo_point |
43+
| service.status.\*.histogram | | object |
2544
| source.geo.location | Longitude and latitude. | geo_point |

0 commit comments

Comments
 (0)