diff --git a/exporter/elasticsearchexporter/internal/elasticsearch/mapping_hint.go b/exporter/elasticsearchexporter/internal/elasticsearch/mapping_hint.go new file mode 100644 index 000000000000..da9333ee9f4b --- /dev/null +++ b/exporter/elasticsearchexporter/internal/elasticsearch/mapping_hint.go @@ -0,0 +1,44 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package elasticsearch // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter/internal/elasticsearch" + +import ( + "slices" + + "go.opentelemetry.io/collector/pdata/pcommon" +) + +const ( + MappingHintsAttrKey = "elasticsearch.mapping.hints" +) + +type MappingHint string + +const ( + HintAggregateMetricDouble MappingHint = "aggregate_metric_double" + HintDocCount MappingHint = "_doc_count" +) + +type MappingHintGetter struct { + hints []MappingHint +} + +// NewMappingHintGetter creates a new MappingHintGetter +func NewMappingHintGetter(attr pcommon.Map) (g MappingHintGetter) { + v, ok := attr.Get(MappingHintsAttrKey) + if !ok || v.Type() != pcommon.ValueTypeSlice { + return + } + slice := v.Slice() + g.hints = slices.Grow(g.hints, slice.Len()) + for i := range slice.Len() { + g.hints = append(g.hints, MappingHint(slice.At(i).Str())) + } + return +} + +// HasMappingHint checks whether the getter contains the requested mapping hint +func (g MappingHintGetter) HasMappingHint(hint MappingHint) bool { + return slices.Contains(g.hints, hint) +} diff --git a/exporter/elasticsearchexporter/mapping_hint_test.go b/exporter/elasticsearchexporter/internal/elasticsearch/mapping_hint_test.go similarity index 60% rename from exporter/elasticsearchexporter/mapping_hint_test.go rename to exporter/elasticsearchexporter/internal/elasticsearch/mapping_hint_test.go index b0d8aae4dd0a..de6336a1fa41 100644 --- a/exporter/elasticsearchexporter/mapping_hint_test.go +++ b/exporter/elasticsearchexporter/internal/elasticsearch/mapping_hint_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package elasticsearchexporter +package elasticsearch import ( "testing" @@ -14,74 +14,74 @@ func TestHasHint(t *testing.T) { tests := []struct { name string attrsFunc func() pcommon.Map - hint mappingHint + hint MappingHint want bool }{ { name: "empty map", attrsFunc: pcommon.NewMap, - hint: hintAggregateMetricDouble, + hint: HintAggregateMetricDouble, want: false, }, { name: "bad type", attrsFunc: func() pcommon.Map { m := pcommon.NewMap() - m.PutBool(mappingHintsAttrKey, true) + m.PutBool(MappingHintsAttrKey, true) return m }, - hint: hintAggregateMetricDouble, + hint: HintAggregateMetricDouble, want: false, }, { name: "bad inner type", attrsFunc: func() pcommon.Map { m := pcommon.NewMap() - s := m.PutEmptySlice(mappingHintsAttrKey) + s := m.PutEmptySlice(MappingHintsAttrKey) s.AppendEmpty().SetBool(true) return m }, - hint: hintAggregateMetricDouble, + hint: HintAggregateMetricDouble, want: false, }, { name: "hit", attrsFunc: func() pcommon.Map { m := pcommon.NewMap() - s := m.PutEmptySlice(mappingHintsAttrKey) - s.AppendEmpty().SetStr(string(hintAggregateMetricDouble)) + s := m.PutEmptySlice(MappingHintsAttrKey) + s.AppendEmpty().SetStr(string(HintAggregateMetricDouble)) return m }, - hint: hintAggregateMetricDouble, + hint: HintAggregateMetricDouble, want: true, }, { name: "hit 2nd", attrsFunc: func() pcommon.Map { m := pcommon.NewMap() - s := m.PutEmptySlice(mappingHintsAttrKey) - s.AppendEmpty().SetStr(string(hintDocCount)) - s.AppendEmpty().SetStr(string(hintAggregateMetricDouble)) + s := m.PutEmptySlice(MappingHintsAttrKey) + s.AppendEmpty().SetStr(string(HintDocCount)) + s.AppendEmpty().SetStr(string(HintAggregateMetricDouble)) return m }, - hint: hintAggregateMetricDouble, + hint: HintAggregateMetricDouble, want: true, }, { name: "miss", attrsFunc: func() pcommon.Map { m := pcommon.NewMap() - s := m.PutEmptySlice(mappingHintsAttrKey) - s.AppendEmpty().SetStr(string(hintDocCount)) + s := m.PutEmptySlice(MappingHintsAttrKey) + s.AppendEmpty().SetStr(string(HintDocCount)) return m }, - hint: hintAggregateMetricDouble, + hint: HintAggregateMetricDouble, want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, newMappingHintGetter(tt.attrsFunc()).HasMappingHint(tt.hint)) + assert.Equal(t, tt.want, NewMappingHintGetter(tt.attrsFunc()).HasMappingHint(tt.hint)) }) } } diff --git a/exporter/elasticsearchexporter/mapping_hint.go b/exporter/elasticsearchexporter/mapping_hint.go deleted file mode 100644 index 5362335c7b35..000000000000 --- a/exporter/elasticsearchexporter/mapping_hint.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package elasticsearchexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter" - -import ( - "slices" - - "go.opentelemetry.io/collector/pdata/pcommon" -) - -const ( - mappingHintsAttrKey = "elasticsearch.mapping.hints" -) - -type mappingHint string - -const ( - hintAggregateMetricDouble mappingHint = "aggregate_metric_double" - hintDocCount mappingHint = "_doc_count" -) - -type mappingHintGetter struct { - hints []mappingHint -} - -func newMappingHintGetter(attr pcommon.Map) (g mappingHintGetter) { - v, ok := attr.Get(mappingHintsAttrKey) - if !ok || v.Type() != pcommon.ValueTypeSlice { - return - } - slice := v.Slice() - g.hints = slices.Grow(g.hints, slice.Len()) - for i := 0; i < slice.Len(); i++ { - g.hints = append(g.hints, mappingHint(slice.At(i).Str())) - } - return -} - -func (g mappingHintGetter) HasMappingHint(hint mappingHint) bool { - return slices.Contains(g.hints, hint) -} diff --git a/exporter/elasticsearchexporter/model.go b/exporter/elasticsearchexporter/model.go index 1c5bf8a71967..89f1cb1fb68b 100644 --- a/exporter/elasticsearchexporter/model.go +++ b/exporter/elasticsearchexporter/model.go @@ -21,6 +21,7 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace" semconv "go.opentelemetry.io/collector/semconv/v1.22.0" + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter/internal/elasticsearch" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter/internal/exphistogram" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter/internal/objmodel" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/traceutil" @@ -101,7 +102,7 @@ type dataPoint interface { Value() (pcommon.Value, error) DynamicTemplate(pmetric.Metric) string DocCount() uint64 - HasMappingHint(mappingHint) bool + HasMappingHint(elasticsearch.MappingHint) bool Metric() pmetric.Metric } @@ -263,12 +264,12 @@ func (m *encodeModel) encodeMetrics(resource pcommon.Resource, resourceSchemaURL type summaryDataPoint struct { pmetric.SummaryDataPoint - mappingHintGetter + elasticsearch.MappingHintGetter metric pmetric.Metric } func newSummaryDataPoint(metric pmetric.Metric, dp pmetric.SummaryDataPoint) summaryDataPoint { - return summaryDataPoint{SummaryDataPoint: dp, mappingHintGetter: newMappingHintGetter(dp.Attributes()), metric: metric} + return summaryDataPoint{SummaryDataPoint: dp, MappingHintGetter: elasticsearch.NewMappingHintGetter(dp.Attributes()), metric: metric} } func (dp summaryDataPoint) Value() (pcommon.Value, error) { @@ -295,16 +296,16 @@ func (dp summaryDataPoint) Metric() pmetric.Metric { type exponentialHistogramDataPoint struct { pmetric.ExponentialHistogramDataPoint - mappingHintGetter + elasticsearch.MappingHintGetter metric pmetric.Metric } func newExponentialHistogramDataPoint(metric pmetric.Metric, dp pmetric.ExponentialHistogramDataPoint) exponentialHistogramDataPoint { - return exponentialHistogramDataPoint{ExponentialHistogramDataPoint: dp, mappingHintGetter: newMappingHintGetter(dp.Attributes()), metric: metric} + return exponentialHistogramDataPoint{ExponentialHistogramDataPoint: dp, MappingHintGetter: elasticsearch.NewMappingHintGetter(dp.Attributes()), metric: metric} } func (dp exponentialHistogramDataPoint) Value() (pcommon.Value, error) { - if dp.HasMappingHint(hintAggregateMetricDouble) { + if dp.HasMappingHint(elasticsearch.HintAggregateMetricDouble) { vm := pcommon.NewValueMap() m := vm.Map() m.PutDouble("sum", dp.Sum()) @@ -331,7 +332,7 @@ func (dp exponentialHistogramDataPoint) Value() (pcommon.Value, error) { } func (dp exponentialHistogramDataPoint) DynamicTemplate(_ pmetric.Metric) string { - if dp.HasMappingHint(hintAggregateMetricDouble) { + if dp.HasMappingHint(elasticsearch.HintAggregateMetricDouble) { return "summary" } return "histogram" @@ -347,16 +348,16 @@ func (dp exponentialHistogramDataPoint) Metric() pmetric.Metric { type histogramDataPoint struct { pmetric.HistogramDataPoint - mappingHintGetter + elasticsearch.MappingHintGetter metric pmetric.Metric } func newHistogramDataPoint(metric pmetric.Metric, dp pmetric.HistogramDataPoint) histogramDataPoint { - return histogramDataPoint{HistogramDataPoint: dp, mappingHintGetter: newMappingHintGetter(dp.Attributes()), metric: metric} + return histogramDataPoint{HistogramDataPoint: dp, MappingHintGetter: elasticsearch.NewMappingHintGetter(dp.Attributes()), metric: metric} } func (dp histogramDataPoint) Value() (pcommon.Value, error) { - if dp.HasMappingHint(hintAggregateMetricDouble) { + if dp.HasMappingHint(elasticsearch.HintAggregateMetricDouble) { vm := pcommon.NewValueMap() m := vm.Map() m.PutDouble("sum", dp.Sum()) @@ -367,7 +368,7 @@ func (dp histogramDataPoint) Value() (pcommon.Value, error) { } func (dp histogramDataPoint) DynamicTemplate(_ pmetric.Metric) string { - if dp.HasMappingHint(hintAggregateMetricDouble) { + if dp.HasMappingHint(elasticsearch.HintAggregateMetricDouble) { return "summary" } return "histogram" @@ -431,12 +432,12 @@ func histogramToValue(dp pmetric.HistogramDataPoint) (pcommon.Value, error) { type numberDataPoint struct { pmetric.NumberDataPoint - mappingHintGetter + elasticsearch.MappingHintGetter metric pmetric.Metric } func newNumberDataPoint(metric pmetric.Metric, dp pmetric.NumberDataPoint) numberDataPoint { - return numberDataPoint{NumberDataPoint: dp, mappingHintGetter: newMappingHintGetter(dp.Attributes()), metric: metric} + return numberDataPoint{NumberDataPoint: dp, MappingHintGetter: elasticsearch.NewMappingHintGetter(dp.Attributes()), metric: metric} } func (dp numberDataPoint) Value() (pcommon.Value, error) { @@ -724,7 +725,7 @@ func metricOTelHash(dp dataPoint, unit string) uint32 { hasher.Write([]byte(unit)) - mapHashExcludeReservedAttrs(hasher, dp.Attributes(), mappingHintsAttrKey) + mapHashExcludeReservedAttrs(hasher, dp.Attributes(), elasticsearch.MappingHintsAttrKey) return hasher.Sum32() } diff --git a/exporter/elasticsearchexporter/pdata_serializer.go b/exporter/elasticsearchexporter/pdata_serializer.go index 5c59ef814747..9d2fbf82f63c 100644 --- a/exporter/elasticsearchexporter/pdata_serializer.go +++ b/exporter/elasticsearchexporter/pdata_serializer.go @@ -15,6 +15,8 @@ import ( "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/ptrace" + + "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/elasticsearchexporter/internal/elasticsearch" ) const tsLayout = "2006-01-02T15:04:05.000000000Z" @@ -68,7 +70,7 @@ func serializeDataPoints(v *json.Visitor, dataPoints []dataPoint, validationErro // TODO here's potential for more optimization by directly serializing the value instead of allocating a pcommon.Value // the tradeoff is that this would imply a duplicated logic for the ECS mode value, err := dp.Value() - if dp.HasMappingHint(hintDocCount) { + if dp.HasMappingHint(elasticsearch.HintDocCount) { docCount = dp.DocCount() } if err != nil { @@ -296,7 +298,7 @@ func writeAttributes(v *json.Visitor, attributes pcommon.Map, stringifyMapValues _ = v.OnObjectStart(-1, structform.AnyType) attributes.Range(func(k string, val pcommon.Value) bool { switch k { - case dataStreamType, dataStreamDataset, dataStreamNamespace, mappingHintsAttrKey: + case dataStreamType, dataStreamDataset, dataStreamNamespace, elasticsearch.MappingHintsAttrKey: return true } if isGeoAttribute(k, val) {