Skip to content

Commit 335e8fd

Browse files
[exporter/elasticsearch] Update the ECS mode metrics data point hasher to exclude the elasticsearch.mapping.hints attribute (open-telemetry#45887)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description This PR updates the ECS mode metrics data point hasher to exclude the `elasticsearch.mapping.hints` attribute. This is helpful for aggregated metrics generated by the https://github.com/elastic/opentelemetry-collector-components/tree/main/connector/elasticapmconnector, since it generates metrics where the only difference is the `elasticsearch.mapping.hints` attribute value. This also aligns with the OTEL mode metrics data point hasher. Assisted-by: Claude Opus 4.5 <!--Describe what testing was performed and which tests were added.--> #### Testing 1. Add test cases to assert metrics with different `elasticsearch.mapping.hints` values are grouped correctly
1 parent bb4fb45 commit 335e8fd

3 files changed

Lines changed: 83 additions & 1 deletion

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. receiver/filelog)
7+
component: exporter/elasticsearch
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Update the ECS mode metrics data point hasher to exclude the `elasticsearch.mapping.hints` attribute
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [45887]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext: Excluding the `elasticsearch.mapping.hints` attribute will allow similar metric data points to be grouped together and indexed to the same document.
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

exporter/elasticsearchexporter/exporter_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,6 +1931,61 @@ func TestExporterMetrics_Grouping(t *testing.T) {
19311931
})
19321932
}
19331933
})
1934+
1935+
t.Run("mapping hints excluded from grouping", func(t *testing.T) {
1936+
// Test that data points with different mapping hints are grouped together
1937+
// since elasticsearch.mapping.hints should be excluded from the hash.
1938+
for _, mode := range []string{"ecs", "otel"} {
1939+
t.Run(mode, func(t *testing.T) {
1940+
rec := newBulkRecorder()
1941+
server := newESTestServer(t, func(docs []itemRequest) ([]itemResponse, error) {
1942+
rec.Record(docs)
1943+
return itemsAllOK(docs)
1944+
})
1945+
1946+
testMetricsExporter := newTestMetricsExporter(t, server.URL, func(cfg *Config) {
1947+
cfg.Mapping.Mode = mode
1948+
})
1949+
1950+
metrics := pmetric.NewMetrics()
1951+
resource := metrics.ResourceMetrics().AppendEmpty()
1952+
scope := resource.ScopeMetrics().AppendEmpty()
1953+
1954+
// Metric with mapping hints
1955+
fooMetric := scope.Metrics().AppendEmpty()
1956+
fooMetric.SetName("metric.foo")
1957+
fooDp := fooMetric.SetEmptyGauge().DataPoints().AppendEmpty()
1958+
fooDp.SetDoubleValue(1.0)
1959+
hints := fooDp.Attributes().PutEmptySlice(elasticsearch.MappingHintsAttrKey)
1960+
hints.AppendEmpty().SetStr(string(elasticsearch.HintAggregateMetricDouble))
1961+
1962+
// Metric without mapping hints - should be grouped with the above
1963+
barMetric := scope.Metrics().AppendEmpty()
1964+
barMetric.SetName("metric.bar")
1965+
barDp := barMetric.SetEmptyGauge().DataPoints().AppendEmpty()
1966+
barDp.SetDoubleValue(2.0)
1967+
1968+
// Metric with different mapping hints - should still be grouped
1969+
bazMetric := scope.Metrics().AppendEmpty()
1970+
bazMetric.SetName("metric.baz")
1971+
bazDp := bazMetric.SetEmptyGauge().DataPoints().AppendEmpty()
1972+
bazDp.SetDoubleValue(3.0)
1973+
bazHints := bazDp.Attributes().PutEmptySlice(elasticsearch.MappingHintsAttrKey)
1974+
bazHints.AppendEmpty().SetStr(string(elasticsearch.HintDocCount))
1975+
1976+
mustSendMetrics(t, testMetricsExporter, metrics)
1977+
1978+
rec.WaitItems(1)
1979+
assert.Len(t, rec.Items(), 1)
1980+
// Sanity check that all metrics are included in a single document
1981+
// ECS mode uses short names (foo, bar, baz), OTel mode uses full names (metric.foo, etc.)
1982+
doc := string(rec.Items()[0].Document)
1983+
assert.Contains(t, doc, "foo")
1984+
assert.Contains(t, doc, "bar")
1985+
assert.Contains(t, doc, "baz")
1986+
})
1987+
}
1988+
})
19341989
}
19351990

19361991
func mapToDistinct(m map[string]any) attribute.Distinct {

exporter/elasticsearchexporter/internal/metricgroup/hasher.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (h *ECSDataPointHasher) HashKey() HashKey {
7070
binary.LittleEndian.PutUint64(timestampBuf, uint64(h.dp.Timestamp()))
7171
_, _ = hasher.Write(timestampBuf)
7272

73-
mapHashSortedExcludeReservedAttrs(hasher, merged)
73+
mapHashSortedExcludeReservedAttrs(hasher, merged, elasticsearch.MappingHintsAttrKey)
7474

7575
return HashKey{
7676
dpHash: hasher.Sum64(),

0 commit comments

Comments
 (0)