Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chore] Method that sorts Datapoint Slice by Attribute key #23068

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ package golden // import "github.com/open-telemetry/opentelemetry-collector-cont

import (
"sort"
"strings"

"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)

// sorts all Resource Metrics attributes and Datapoint Slice metric attributes
// sorts all Resource Metrics attributes and Datapoint Slice metric attributes and all Datapoint slices
BominRahmani marked this conversation as resolved.
Show resolved Hide resolved
func sortMetrics(ms pmetric.Metrics) {
rms := ms.ResourceMetrics()
for i := 0; i < rms.Len(); i++ {
Expand Down Expand Up @@ -51,6 +52,7 @@ func sortMetrics(ms pmetric.Metrics) {
}
}
}
sortMetricDataPointSlices(ms)
BominRahmani marked this conversation as resolved.
Show resolved Hide resolved
}

// sortAttributeMap sorts the attributes of a pcommon.Map according to the alphanumeric ordering of the keys
Expand Down Expand Up @@ -85,3 +87,77 @@ func sortAttributeMap(mp pcommon.Map) {
}
tempMap.CopyTo(mp)
}

// sortMetricDataPointSlices sorts the datapoint slice of a pmetric.Metrics according to the alphanumeric ordering of map key
BominRahmani marked this conversation as resolved.
Show resolved Hide resolved
func sortMetricDataPointSlices(ms pmetric.Metrics) {
for i := 0; i < ms.ResourceMetrics().Len(); i++ {
for j := 0; j < ms.ResourceMetrics().At(i).ScopeMetrics().Len(); j++ {
for k := 0; k < ms.ResourceMetrics().At(i).ScopeMetrics().At(j).Metrics().Len(); k++ {
m := ms.ResourceMetrics().At(i).ScopeMetrics().At(j).Metrics().At(k)
switch m.Type() {
case pmetric.MetricTypeGauge:
sortNumberDataPointSlice(m.Gauge().DataPoints())
case pmetric.MetricTypeSum:
sortNumberDataPointSlice(m.Sum().DataPoints())
case pmetric.MetricTypeHistogram:
sortHistogramDataPointSlice(m.Histogram().DataPoints())
case pmetric.MetricTypeExponentialHistogram:
sortExponentialHistogramDataPointSlice(m.ExponentialHistogram().DataPoints())
case pmetric.MetricTypeSummary:
sortSummaryDataPointSlice(m.Summary().DataPoints())
}
}
}
}
}

func sortNumberDataPointSlice(ndps pmetric.NumberDataPointSlice) {
ndps.Sort(func(a, b pmetric.NumberDataPoint) bool {
return compareMaps(a.Attributes(), b.Attributes()) < 0
})
}

func sortSummaryDataPointSlice(sdps pmetric.SummaryDataPointSlice) {
sdps.Sort(func(a, b pmetric.SummaryDataPoint) bool {
return compareMaps(a.Attributes(), b.Attributes()) < 0
})
}

func sortHistogramDataPointSlice(hdps pmetric.HistogramDataPointSlice) {
hdps.Sort(func(a, b pmetric.HistogramDataPoint) bool {
return compareMaps(a.Attributes(), b.Attributes()) < 0
})
}

func sortExponentialHistogramDataPointSlice(ehdps pmetric.ExponentialHistogramDataPointSlice) {
ehdps.Sort(func(a, b pmetric.ExponentialHistogramDataPoint) bool {
return compareMaps(a.Attributes(), b.Attributes()) < 0
})
}

func compareMaps(a, b pcommon.Map) int {
sortAttributeMap(a)
sortAttributeMap(b)

if a.Len() != b.Len() {
return a.Len() - b.Len()
}

var aKeys, bKeys []string
a.Range(func(k string, _ pcommon.Value) bool {
aKeys = append(aKeys, k)
return true
})
b.Range(func(k string, _ pcommon.Value) bool {
bKeys = append(bKeys, k)
return true
})

for i := 0; i < len(aKeys); i++ {
if aKeys[i] != bKeys[i] {
return strings.Compare(aKeys[i], bKeys[i])
BominRahmani marked this conversation as resolved.
Show resolved Hide resolved
}
}

return 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
package golden

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/pdata/pcommon"
)

Expand Down Expand Up @@ -42,3 +44,15 @@ func TestSortAttributes(t *testing.T) {
}

}

func TestSortMetricDatapointSlice(t *testing.T) {
beforePath := filepath.Join("testdata", "sort-datapoint-slice", "before.yaml")
afterPath := filepath.Join("testdata", "sort-datapoint-slice", "after.yaml")
before, err := ReadMetrics(beforePath)
require.NoError(t, err)
after, err := ReadMetrics(afterPath)
require.NoError(t, err)
sortMetricDataPointSlices(before)
require.Equal(t, before, after)

BominRahmani marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
resourceMetrics:
- resource:
scopeMetrics:
- metrics:
- description: The number of bytes which have flowed through the network interface.
name: nsxt.node.network.io
sum:
aggregationTemporality: 2
dataPoints:
- asInt: "0"
attributes:
- key: a
value:
stringValue: AAAA
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: b
value:
stringValue: BBBBFirst
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: b
value:
stringValue: BBBBSecond
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: c
value:
stringValue: CCCC
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: x
value:
stringValue: InnerAttributeSort
- key: z
value:
stringValue: DDDD
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
isMonotonic: true
unit: By
scope:
name: otelcol/nsxtreceiver
version: latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
resourceMetrics:
- resource:
scopeMetrics:
- metrics:
- description: The number of bytes which have flowed through the network interface.
name: nsxt.node.network.io
sum:
aggregationTemporality: 2
dataPoints:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have some additional data points that exercise the sorting of attributes within a map? Further, can we have some that require comparison beyond the first key?

  • a
  • b, a
  • c, b
  • c, b, a
  • c, a, d

- asInt: "0"
attributes:
- key: a
value:
stringValue: AAAA
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to omit these fields for this test, as they only distract from the point of the test.

- asInt: "0"
attributes:
- key: z
value:
stringValue: DDDD
- key: x
value:
stringValue: InnerAttributeSort
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: c
value:
stringValue: CCCC
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: b
value:
stringValue: BBBBFirst
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
- asInt: "0"
attributes:
- key: b
value:
stringValue: BBBBSecond
djaglowski marked this conversation as resolved.
Show resolved Hide resolved
startTimeUnixNano: "1111111111111111111"
timeUnixNano: "1111111111111111111"
isMonotonic: true
unit: By
scope:
name: otelcol/nsxtreceiver
version: latest
2 changes: 1 addition & 1 deletion receiver/mysqlreceiver/testdata/scraper/expected.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1666,7 +1666,7 @@ resourceMetrics:
startTimeUnixNano: "1644862687825728000"
timeUnixNano: "1644862687825772000"
isMonotonic: true
unit: "s"
unit: s
BominRahmani marked this conversation as resolved.
Show resolved Hide resolved
scope:
name: otelcol/mysqlreceiver
version: latest