Skip to content

Commit d567ce5

Browse files
committed
[prometheusremotewritereceiver] add sample stats headers
1 parent 6e092c1 commit d567ce5

File tree

3 files changed

+107
-11
lines changed

3 files changed

+107
-11
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. filelogreceiver)
7+
component: 'prometheusremotewritereceiver'
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add a count of all successfully written samples when elements were processed.
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: [37277]
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: [user]

receiver/prometheusremotewritereceiver/receiver.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,15 @@ func (prw *prometheusRemoteWriteReceiver) parseProto(contentType string) (promco
231231

232232
// translateV2 translates a v2 remote-write request into OTLP metrics.
233233
// translate is not feature complete.
234-
//
235-
//nolint:unparam
236234
func (prw *prometheusRemoteWriteReceiver) translateV2(_ context.Context, req *writev2.Request) (pmetric.Metrics, promremote.WriteResponseStats, error) {
237235
var (
238236
badRequestErrors error
239237
otelMetrics = pmetric.NewMetrics()
240238
labelsBuilder = labels.NewScratchBuilder(0)
241-
stats = promremote.WriteResponseStats{}
239+
// More about stats: https://github.com/prometheus/docs/blob/main/docs/specs/prw/remote_write_spec_2_0.md#required-written-response-headers
240+
// TODO: add histograms and exemplars to the stats. Histograms can be added after this PR be merged. Ref #39864
241+
// Exemplars should be implemented to add them to the stats.
242+
stats = promremote.WriteResponseStats{}
242243
// The key is composed by: resource_hash:scope_name:scope_version:metric_name:unit:type
243244
metricCache = make(map[uint64]pmetric.Metric)
244245
)
@@ -367,9 +368,11 @@ func (prw *prometheusRemoteWriteReceiver) translateV2(_ context.Context, req *wr
367368
// Otherwise, we append the samples to the existing metric.
368369
switch ts.Metadata.Type {
369370
case writev2.Metadata_METRIC_TYPE_GAUGE:
370-
addNumberDatapoints(metric.Gauge().DataPoints(), ls, ts)
371+
addNumberDatapoints(metric.Gauge().DataPoints(), ls, ts, &stats)
372+
stats.Confirmed = true
371373
case writev2.Metadata_METRIC_TYPE_COUNTER:
372-
addNumberDatapoints(metric.Sum().DataPoints(), ls, ts)
374+
addNumberDatapoints(metric.Sum().DataPoints(), ls, ts, &stats)
375+
stats.Confirmed = true
373376
case writev2.Metadata_METRIC_TYPE_HISTOGRAM:
374377
addHistogramDatapoints(metric.Histogram().DataPoints(), ls, ts)
375378
case writev2.Metadata_METRIC_TYPE_SUMMARY:
@@ -400,7 +403,7 @@ func parseJobAndInstance(dest pcommon.Map, job, instance string) {
400403
}
401404

402405
// addNumberDatapoints adds the labels to the datapoints attributes.
403-
func addNumberDatapoints(datapoints pmetric.NumberDataPointSlice, ls labels.Labels, ts writev2.TimeSeries) {
406+
func addNumberDatapoints(datapoints pmetric.NumberDataPointSlice, ls labels.Labels, ts writev2.TimeSeries, stats *promremote.WriteResponseStats) {
404407
// Add samples from the timeseries
405408
for _, sample := range ts.Samples {
406409
dp := datapoints.AppendEmpty()
@@ -418,6 +421,7 @@ func addNumberDatapoints(datapoints pmetric.NumberDataPointSlice, ls labels.Labe
418421
}
419422
attributes.PutStr(l.Name, l.Value)
420423
}
424+
stats.Samples++
421425
}
422426
}
423427

receiver/prometheusremotewritereceiver/receiver_test.go

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,34 +87,65 @@ func setupMetricsReceiver(t *testing.T) *prometheusRemoteWriteReceiver {
8787

8888
func TestHandlePRWContentTypeNegotiation(t *testing.T) {
8989
for _, tc := range []struct {
90-
name string
91-
contentType string
92-
expectedCode int
90+
name string
91+
contentType string
92+
expectedCode int
93+
expectedStats remote.WriteResponseStats
9394
}{
9495
{
9596
name: "no content type",
9697
contentType: "",
9798
expectedCode: http.StatusUnsupportedMediaType,
99+
expectedStats: remote.WriteResponseStats{
100+
Confirmed: false,
101+
Samples: 0,
102+
Histograms: 0,
103+
Exemplars: 0,
104+
},
98105
},
99106
{
100107
name: "unsupported content type",
101108
contentType: "application/json",
102109
expectedCode: http.StatusUnsupportedMediaType,
110+
expectedStats: remote.WriteResponseStats{
111+
Confirmed: false,
112+
Samples: 0,
113+
Histograms: 0,
114+
Exemplars: 0,
115+
},
103116
},
104117
{
105118
name: "x-protobuf/no proto parameter",
106119
contentType: "application/x-protobuf",
107120
expectedCode: http.StatusUnsupportedMediaType,
121+
expectedStats: remote.WriteResponseStats{
122+
Confirmed: false,
123+
Samples: 0,
124+
Histograms: 0,
125+
Exemplars: 0,
126+
},
108127
},
109128
{
110129
name: "x-protobuf/v1 proto parameter",
111130
contentType: fmt.Sprintf("application/x-protobuf;proto=%s", promconfig.RemoteWriteProtoMsgV1),
112131
expectedCode: http.StatusUnsupportedMediaType,
132+
expectedStats: remote.WriteResponseStats{
133+
Confirmed: false,
134+
Samples: 0,
135+
Histograms: 0,
136+
Exemplars: 0,
137+
},
113138
},
114139
{
115140
name: "x-protobuf/v2 proto parameter",
116141
contentType: fmt.Sprintf("application/x-protobuf;proto=%s", promconfig.RemoteWriteProtoMsgV2),
117142
expectedCode: http.StatusNoContent,
143+
expectedStats: remote.WriteResponseStats{
144+
Confirmed: true,
145+
Samples: 0,
146+
Histograms: 0,
147+
Exemplars: 0,
148+
},
118149
},
119150
} {
120151
t.Run(tc.name, func(t *testing.T) {
@@ -170,6 +201,12 @@ func TestTranslateV2(t *testing.T) {
170201
},
171202
},
172203
expectError: "missing metric name in labels",
204+
expectedStats: remote.WriteResponseStats{
205+
Confirmed: false,
206+
Samples: 0,
207+
Histograms: 0,
208+
Exemplars: 0,
209+
},
173210
},
174211
{
175212
name: "duplicate label",
@@ -183,6 +220,12 @@ func TestTranslateV2(t *testing.T) {
183220
},
184221
},
185222
expectError: `duplicate label "__name__" in labels`,
223+
expectedStats: remote.WriteResponseStats{
224+
Confirmed: false,
225+
Samples: 0,
226+
Histograms: 0,
227+
Exemplars: 0,
228+
},
186229
},
187230
{
188231
name: "UnitRef bigger than symbols length",
@@ -266,7 +309,12 @@ func TestTranslateV2(t *testing.T) {
266309

267310
return expected
268311
}(),
269-
expectedStats: remote.WriteResponseStats{},
312+
expectedStats: remote.WriteResponseStats{
313+
Confirmed: true,
314+
Samples: 3,
315+
Histograms: 0,
316+
Exemplars: 0,
317+
},
270318
},
271319
{
272320
name: "timeseries with different scopes",
@@ -342,7 +390,12 @@ func TestTranslateV2(t *testing.T) {
342390

343391
return expected
344392
}(),
345-
expectedStats: remote.WriteResponseStats{},
393+
expectedStats: remote.WriteResponseStats{
394+
Confirmed: true,
395+
Samples: 3,
396+
Histograms: 0,
397+
Exemplars: 0,
398+
},
346399
},
347400
{
348401
name: "separate timeseries - same labels - should be same datapointslice",
@@ -426,6 +479,12 @@ func TestTranslateV2(t *testing.T) {
426479

427480
return expected
428481
}(),
482+
expectedStats: remote.WriteResponseStats{
483+
Confirmed: true,
484+
Samples: 3,
485+
Histograms: 0,
486+
Exemplars: 0,
487+
},
429488
},
430489
{
431490
name: "service with target_info metric",
@@ -488,6 +547,12 @@ func TestTranslateV2(t *testing.T) {
488547

489548
return metrics
490549
}(),
550+
expectedStats: remote.WriteResponseStats{
551+
Confirmed: true,
552+
Samples: 1,
553+
Histograms: 0,
554+
Exemplars: 0,
555+
},
491556
},
492557
} {
493558
t.Run(tc.name, func(t *testing.T) {

0 commit comments

Comments
 (0)