Skip to content

Commit 408c87e

Browse files
VihasMakwanasongy23
authored andcommitted
[receiver/prometheusremotewrite] skip emitting empty metrics (open-telemetry#44149)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description We should ideally empty a metric only if it has some datapoints in it. Right now, we can emit empty metric if the `target_info` arrives first and normal metrics arrives in subsequent request. This PR adds a simple check to skip `ConsumeMetrics` if metric count is 0. <!--Describe what testing was performed and which tests were added.--> #### Testing Updated tests --------- Co-authored-by: Yang Song <[email protected]>
1 parent 25b90c8 commit 408c87e

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed
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: receiver/prometheusremotewrite
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Skip emitting empty metrics.
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: [44149]
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:
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: []

receiver/prometheusremotewritereceiver/receiver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ func (prw *prometheusRemoteWriteReceiver) handlePRW(w http.ResponseWriter, req *
194194

195195
w.WriteHeader(http.StatusNoContent)
196196

197+
// Return if metric count is 0.
198+
if m.MetricCount() == 0 {
199+
return
200+
}
197201
obsrecvCtx := prw.obsrecv.StartMetricsOp(req.Context())
198202
err = prw.nextConsumer.ConsumeMetrics(req.Context(), m)
199203
if err != nil {

receiver/prometheusremotewritereceiver/receiver_test.go

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,21 +1509,6 @@ func TestTargetInfoWithMultipleRequests(t *testing.T) {
15091509
attrs.PutStr("cloud_provider", "gcp")
15101510
attrs.PutStr("region", "us-central1")
15111511

1512-
return metrics
1513-
}()
1514-
1515-
// Using the same expected metrics for both tests, because we are just checking if the order of the requests changes the result.
1516-
expectedIndex1 := func() pmetric.Metrics {
1517-
metrics := pmetric.NewMetrics()
1518-
rm := metrics.ResourceMetrics().AppendEmpty()
1519-
attrs := rm.Resource().Attributes()
1520-
attrs.PutStr("service.namespace", "production")
1521-
attrs.PutStr("service.name", "service_a")
1522-
attrs.PutStr("service.instance.id", "host1")
1523-
attrs.PutStr("machine_type", "n1-standard-1")
1524-
attrs.PutStr("cloud_provider", "gcp")
1525-
attrs.PutStr("region", "us-central1")
1526-
15271512
sm := rm.ScopeMetrics().AppendEmpty()
15281513
sm.Scope().SetName("OpenTelemetry Collector")
15291514
sm.Scope().SetVersion("latest")
@@ -1568,11 +1553,10 @@ func TestTargetInfoWithMultipleRequests(t *testing.T) {
15681553
assert.NoError(t, err)
15691554
assert.Equal(t, http.StatusNoContent, resp.StatusCode, string(body))
15701555
}
1571-
1572-
// index 0 is related to the target_info metric that is the first request.
1556+
// Only one metric should be emitted
1557+
assert.Len(t, mockConsumer.metrics, 1)
1558+
// index 0 is related to the join between the target_info and the normal metric.
15731559
assert.NoError(t, pmetrictest.CompareMetrics(expectedIndex0, mockConsumer.metrics[0]))
1574-
// index 1 is related to the join between the target_info and the normal metric.
1575-
assert.NoError(t, pmetrictest.CompareMetrics(expectedIndex1, mockConsumer.metrics[1]))
15761560
})
15771561
}
15781562
}
@@ -1768,11 +1752,11 @@ func TestLRUCacheResourceMetrics(t *testing.T) {
17681752
}
17691753

17701754
// As target_info and metric1 have the same job/instance, they generate the same end metric: mockConsumer.metrics[0].
1771-
assert.NoError(t, pmetrictest.CompareMetrics(expectedMetrics1, mockConsumer.metrics[1]))
1772-
// As metric2 have different job/instance, it generates a different end metric: mockConsumer.metrics[2]. At this point, the cache is full it should evict the target_info metric to store the metric2.
1773-
assert.NoError(t, pmetrictest.CompareMetrics(expectedMetrics2, mockConsumer.metrics[2]))
1755+
assert.NoError(t, pmetrictest.CompareMetrics(expectedMetrics1, mockConsumer.metrics[0]))
1756+
// As metric2 have different job/instance, it generates a different end metric: mockConsumer.metrics[1]. At this point, the cache is full it should evict the target_info metric to store the metric2.
1757+
assert.NoError(t, pmetrictest.CompareMetrics(expectedMetrics2, mockConsumer.metrics[1]))
17741758
// As just have 1 slot in the cache, but the cache for metric1 was evicted, this metric1_1 should generate a new resource metric, even having the same job/instance than the metric1.
1775-
assert.NoError(t, pmetrictest.CompareMetrics(expectedMetrics1_1, mockConsumer.metrics[3]))
1759+
assert.NoError(t, pmetrictest.CompareMetrics(expectedMetrics1_1, mockConsumer.metrics[2]))
17761760
}
17771761

17781762
func buildMetaDataMapByID(ms pmetric.Metrics) map[string]map[string]any {

0 commit comments

Comments
 (0)