diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 014c554435b..051874c3b1a 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -210,6 +210,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Add `aws_ec2` provider for autodiscover. {issue}12518[12518] {pull}14823[14823] - Add monitoring variable `libbeat.config.scans` to distinguish scans of the configuration directory from actual reloads of its contents. {pull}16440[16440] - Add support for multiple password in redis output. {issue}16058[16058] {pull}16206[16206] +- Add support for Histogram type in fields.yml {pull}16570[16570] - Windows .exe files now have embedded file version info. {issue}15232[15232]t - Remove experimental flag from `setup.template.append_fields` {pull}16576[16576] - Add `add_cloudfoundry_metadata` processor to annotate events with Cloud Foundry application data. {pull}16621[16621] diff --git a/libbeat/mapping/field.go b/libbeat/mapping/field.go index 66cde47e834..66a580dac5e 100644 --- a/libbeat/mapping/field.go +++ b/libbeat/mapping/field.go @@ -134,7 +134,7 @@ func (f *Field) validateType() error { return geoPointType.validate(f.Format) case "date_range": return dateRangeType.validate(f.Format) - case "boolean", "binary", "ip", "alias", "array": + case "boolean", "binary", "ip", "alias", "array", "histogram": if f.Format != "" { return fmt.Errorf("no format expected for field %s, found: %s", f.Name, f.Format) } diff --git a/libbeat/template/processor.go b/libbeat/template/processor.go index 30e8bdd8b1c..36fd8c549a8 100644 --- a/libbeat/template/processor.go +++ b/libbeat/template/processor.go @@ -80,6 +80,8 @@ func (p *Processor) Process(fields mapping.Fields, state *fieldState, output com indexMapping = p.array(&field) case "alias": indexMapping = p.alias(&field) + case "histogram": + indexMapping = p.histogram(&field) case "group": indexMapping = common.MapStr{} if field.Dynamic.Value != nil { @@ -287,6 +289,18 @@ func (p *Processor) alias(f *mapping.Field) common.MapStr { return properties } +func (p *Processor) histogram(f *mapping.Field) common.MapStr { + // Histograms were introduced in Elasticsearch 7.6, ignore if unsupported + if p.EsVersion.LessThan(common.MustNewVersion("7.6.0")) { + return nil + } + + properties := getDefaultProperties(f) + properties["type"] = "histogram" + + return properties +} + func (p *Processor) object(f *mapping.Field) common.MapStr { matchType := func(onlyType string, mt string) string { if mt != "" { @@ -324,6 +338,9 @@ func (p *Processor) object(f *mapping.Field) common.MapStr { case "byte", "double", "float", "long", "short", "boolean": dynProperties["type"] = otp.ObjectType addDynamicTemplate(f, dynProperties, matchType(otp.ObjectType, otp.ObjectTypeMappingType)) + case "histogram": + dynProperties["type"] = otp.ObjectType + addDynamicTemplate(f, dynProperties, matchType("*", otp.ObjectTypeMappingType)) } } diff --git a/libbeat/template/processor_test.go b/libbeat/template/processor_test.go index 55859403ec5..8d4e6c2235a 100644 --- a/libbeat/template/processor_test.go +++ b/libbeat/template/processor_test.go @@ -34,6 +34,7 @@ func TestProcessor(t *testing.T) { pEsVersion2 := &Processor{EsVersion: *common.MustNewVersion("2.0.0")} pEsVersion64 := &Processor{EsVersion: *common.MustNewVersion("6.4.0")} pEsVersion63 := &Processor{EsVersion: *common.MustNewVersion("6.3.6")} + pEsVersion76 := &Processor{EsVersion: *common.MustNewVersion("7.6.0")} tests := []struct { output common.MapStr @@ -300,6 +301,14 @@ func TestProcessor(t *testing.T) { output: migrationP.alias(&mapping.Field{Type: "alias", AliasPath: "a.f", MigrationAlias: true}), expected: common.MapStr{"path": "a.f", "type": "alias"}, }, + { + output: p.histogram(&mapping.Field{Type: "histogram"}), + expected: nil, + }, + { + output: pEsVersion76.histogram(&mapping.Field{Type: "histogram"}), + expected: common.MapStr{"type": "histogram"}, + }, } for _, test := range tests {