Skip to content

Commit

Permalink
feat: prom translation rw2 add support for labels (#35751)
Browse files Browse the repository at this point in the history
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description
Adding full support for handling labels.

<!-- Issue number (e.g. #1234) or full URL to issue, if applicable. -->
#### Link to tracking issue #33661
Fixes

<!--Describe what testing was performed and which tests were added.-->
#### Testing

<!--Describe the documentation added.-->
#### Documentation

<!--Please delete paragraphs that you did not use before submitting.-->

---------

Signed-off-by: Juraj Michalek <[email protected]>
Co-authored-by: Arthur Silva Sens <[email protected]>
Co-authored-by: David Ashpole <[email protected]>
  • Loading branch information
3 people authored Oct 23, 2024
1 parent 7daddba commit c5b6746
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 26 deletions.
27 changes: 27 additions & 0 deletions .chloggen/jm-prom-translation-rw2-add-support-for-labels.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: pkg/translator/prometheusremotewrite

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "`FromMetricsV2` now transforms attributes into labels."

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [33661]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
26 changes: 18 additions & 8 deletions pkg/translator/prometheusremotewrite/metrics_to_prw_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"fmt"
"strconv"

"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/prompb"
writev2 "github.com/prometheus/prometheus/prompb/io/prometheus/write/v2"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
Expand Down Expand Up @@ -49,6 +49,7 @@ func (c *prometheusConverterV2) fromMetrics(md pmetric.Metrics, settings Setting
resourceMetricsSlice := md.ResourceMetrics()
for i := 0; i < resourceMetricsSlice.Len(); i++ {
resourceMetrics := resourceMetricsSlice.At(i)
resource := resourceMetrics.Resource()
scopeMetricsSlice := resourceMetrics.ScopeMetrics()
// keep track of the most recent timestamp in the ResourceMetrics for
// use with the "target" info metric
Expand Down Expand Up @@ -77,7 +78,7 @@ func (c *prometheusConverterV2) fromMetrics(md pmetric.Metrics, settings Setting
errs = multierr.Append(errs, fmt.Errorf("empty data points. %s is dropped", metric.Name()))
break
}
c.addGaugeNumberDataPoints(dataPoints, promName)
c.addGaugeNumberDataPoints(dataPoints, resource, settings, promName)
case pmetric.MetricTypeSum:
// TODO implement
case pmetric.MetricTypeHistogram:
Expand Down Expand Up @@ -107,16 +108,25 @@ func (c *prometheusConverterV2) timeSeries() []writev2.TimeSeries {
return allTS
}

func (c *prometheusConverterV2) addSample(sample *writev2.Sample, lbls labels.Labels) *writev2.TimeSeries {
func (c *prometheusConverterV2) addSample(sample *writev2.Sample, lbls []prompb.Label) *writev2.TimeSeries {
if sample == nil || len(lbls) == 0 {
// This shouldn't happen
return nil
}
ts := &writev2.TimeSeries{}
ts.LabelsRefs = c.symbolTable.SymbolizeLabels(lbls, ts.LabelsRefs)
ts.Samples = append(ts.Samples, *sample)

c.unique[lbls.Hash()] = ts
buf := make([]uint32, 0, len(lbls)*2)
var off uint32
for _, l := range lbls {
off = c.symbolTable.Symbolize(l.Name)
buf = append(buf, off)
off = c.symbolTable.Symbolize(l.Value)
buf = append(buf, off)
}
ts := writev2.TimeSeries{
LabelsRefs: buf,
Samples: []writev2.Sample{*sample},
}
c.unique[timeSeriesSignature(lbls)] = &ts

return ts
return &ts
}
10 changes: 4 additions & 6 deletions pkg/translator/prometheusremotewrite/metrics_to_prw_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,16 @@ func TestFromMetricsV2(t *testing.T) {
want := func() map[string]*writev2.TimeSeries {
return map[string]*writev2.TimeSeries{
"0": {
LabelsRefs: []uint32{1, 2},
LabelsRefs: []uint32{1, 2, 3, 4, 5, 6, 7, 8},
Samples: []writev2.Sample{
{Timestamp: convertTimeStamp(pcommon.Timestamp(ts)), Value: 1.23},
},
},
}
}
wantedSymbols := []string{"", "series_name_2", "value-2", "series_name_3", "value-3", "__name__", "gauge_1", "series_name_1", "value-1"}
tsMap, symbolsTable, err := FromMetricsV2(payload.Metrics(), settings)
wanted := want()
require.NoError(t, err)
require.NotNil(t, tsMap)
require.Equal(t, wanted, tsMap)
require.NotNil(t, symbolsTable)

require.Equal(t, want(), tsMap)
require.ElementsMatch(t, wantedSymbols, symbolsTable.Symbols())
}
21 changes: 12 additions & 9 deletions pkg/translator/prometheusremotewrite/number_data_points_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@ import (
"math"

"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/value"
writev2 "github.com/prometheus/prometheus/prompb/io/prometheus/write/v2"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)

func (c *prometheusConverterV2) addGaugeNumberDataPoints(dataPoints pmetric.NumberDataPointSlice, name string) {
func (c *prometheusConverterV2) addGaugeNumberDataPoints(dataPoints pmetric.NumberDataPointSlice,
resource pcommon.Resource, settings Settings, name string) {
for x := 0; x < dataPoints.Len(); x++ {
pt := dataPoints.At(x)
// TODO implement support for labels

labels := labels.Labels{
labels.Label{
Name: model.MetricNameLabel,
Value: name,
},
}
labels := createAttributes(
resource,
pt.Attributes(),
settings.ExternalLabels,
nil,
true,
model.MetricNameLabel,
name,
)

sample := &writev2.Sample{
// convert ns to ms
Expand Down
23 changes: 20 additions & 3 deletions pkg/translator/prometheusremotewrite/number_data_points_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,16 @@ func TestPrometheusConverterV2_addGaugeNumberDataPoints(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
metric := tt.metric()
settings := Settings{
Namespace: "",
ExternalLabels: nil,
DisableTargetInfo: false,
ExportCreatedMetric: false,
AddMetricSuffixes: false,
SendMetadata: false,
}
converter := newPrometheusConverterV2()
converter.addGaugeNumberDataPoints(metric.Gauge().DataPoints(), metric.Name())
converter.addGaugeNumberDataPoints(metric.Gauge().DataPoints(), pcommon.NewResource(), settings, metric.Name())
w := tt.want()

diff := cmp.Diff(w, converter.unique, cmpopts.EquateNaNs())
Expand Down Expand Up @@ -150,9 +158,18 @@ func TestPrometheusConverterV2_addGaugeNumberDataPointsDuplicate(t *testing.T) {
}
}

settings := Settings{
Namespace: "",
ExternalLabels: nil,
DisableTargetInfo: false,
ExportCreatedMetric: false,
AddMetricSuffixes: false,
SendMetadata: false,
}

converter := newPrometheusConverterV2()
converter.addGaugeNumberDataPoints(metric1.Gauge().DataPoints(), metric1.Name())
converter.addGaugeNumberDataPoints(metric2.Gauge().DataPoints(), metric2.Name())
converter.addGaugeNumberDataPoints(metric1.Gauge().DataPoints(), pcommon.NewResource(), settings, metric1.Name())
converter.addGaugeNumberDataPoints(metric2.Gauge().DataPoints(), pcommon.NewResource(), settings, metric2.Name())

assert.Equal(t, want(), converter.unique)

Expand Down

0 comments on commit c5b6746

Please sign in to comment.