sort_metrics.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package golden // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden"
  4. import (
  5. "fmt"
  6. "sort"
  7. "strings"
  8. "go.opentelemetry.io/collector/pdata/pcommon"
  9. "go.opentelemetry.io/collector/pdata/pmetric"
  10. )
  11. // sorts all Resource Metrics attributes and Datapoint Slice metric attributes and all Resource, Scope, and Datapoint Slices
  12. func sortMetrics(ms pmetric.Metrics) {
  13. rms := ms.ResourceMetrics()
  14. for i := 0; i < rms.Len(); i++ {
  15. sortAttributeMap(rms.At(i).Resource().Attributes())
  16. ilms := rms.At(i).ScopeMetrics()
  17. for j := 0; j < ilms.Len(); j++ {
  18. sortAttributeMap(ilms.At(j).Scope().Attributes())
  19. metricsList := ilms.At(j).Metrics()
  20. for k := 0; k < metricsList.Len(); k++ {
  21. metric := metricsList.At(k)
  22. //exhaustive:enforce
  23. switch metricsList.At(k).Type() {
  24. case pmetric.MetricTypeGauge:
  25. ds := metric.Gauge().DataPoints()
  26. for l := 0; l < ds.Len(); l++ {
  27. sortAttributeMap(ds.At(l).Attributes())
  28. }
  29. case pmetric.MetricTypeSum:
  30. ds := metric.Sum().DataPoints()
  31. for l := 0; l < ds.Len(); l++ {
  32. sortAttributeMap(ds.At(l).Attributes())
  33. }
  34. case pmetric.MetricTypeHistogram:
  35. ds := metric.Histogram().DataPoints()
  36. for l := 0; l < ds.Len(); l++ {
  37. sortAttributeMap(ds.At(l).Attributes())
  38. }
  39. case pmetric.MetricTypeExponentialHistogram:
  40. ds := metric.ExponentialHistogram().DataPoints()
  41. for l := 0; l < ds.Len(); l++ {
  42. sortAttributeMap(ds.At(l).Attributes())
  43. }
  44. case pmetric.MetricTypeSummary:
  45. ds := metric.Summary().DataPoints()
  46. for l := 0; l < ds.Len(); l++ {
  47. sortAttributeMap(ds.At(l).Attributes())
  48. }
  49. }
  50. }
  51. }
  52. }
  53. sortResources(ms)
  54. sortScopes(ms)
  55. sortMetricDataPointSlices(ms)
  56. }
  57. // sortAttributeMap sorts the attributes of a pcommon.Map according to the alphanumeric ordering of the keys
  58. func sortAttributeMap(mp pcommon.Map) {
  59. tempMap := pcommon.NewMap()
  60. keys := []string{}
  61. mp.Range(func(key string, _ pcommon.Value) bool {
  62. keys = append(keys, key)
  63. return true
  64. })
  65. sort.Strings(keys)
  66. for _, k := range keys {
  67. value, exists := mp.Get(k)
  68. if exists {
  69. switch value.Type() {
  70. case pcommon.ValueTypeStr:
  71. tempMap.PutStr(k, value.Str())
  72. case pcommon.ValueTypeBool:
  73. tempMap.PutBool(k, value.Bool())
  74. case pcommon.ValueTypeInt:
  75. tempMap.PutInt(k, value.Int())
  76. case pcommon.ValueTypeDouble:
  77. tempMap.PutDouble(k, value.Double())
  78. case pcommon.ValueTypeMap:
  79. value.Map().CopyTo(tempMap.PutEmptyMap(k))
  80. case pcommon.ValueTypeSlice:
  81. value.Slice().CopyTo(tempMap.PutEmptySlice(k))
  82. case pcommon.ValueTypeBytes:
  83. value.Bytes().CopyTo(tempMap.PutEmptyBytes(k))
  84. }
  85. }
  86. }
  87. tempMap.CopyTo(mp)
  88. }
  89. // sortMetricDataPointSlices sorts the datapoint slice of a pmetric.Metrics according to the alphanumeric ordering of map key
  90. func sortMetricDataPointSlices(ms pmetric.Metrics) {
  91. for i := 0; i < ms.ResourceMetrics().Len(); i++ {
  92. for j := 0; j < ms.ResourceMetrics().At(i).ScopeMetrics().Len(); j++ {
  93. for k := 0; k < ms.ResourceMetrics().At(i).ScopeMetrics().At(j).Metrics().Len(); k++ {
  94. m := ms.ResourceMetrics().At(i).ScopeMetrics().At(j).Metrics().At(k)
  95. //exhaustive:enforce
  96. switch m.Type() {
  97. case pmetric.MetricTypeGauge:
  98. sortNumberDataPointSlice(m.Gauge().DataPoints())
  99. case pmetric.MetricTypeSum:
  100. sortNumberDataPointSlice(m.Sum().DataPoints())
  101. case pmetric.MetricTypeHistogram:
  102. sortHistogramDataPointSlice(m.Histogram().DataPoints())
  103. case pmetric.MetricTypeExponentialHistogram:
  104. sortExponentialHistogramDataPointSlice(m.ExponentialHistogram().DataPoints())
  105. case pmetric.MetricTypeSummary:
  106. sortSummaryDataPointSlice(m.Summary().DataPoints())
  107. }
  108. }
  109. }
  110. }
  111. }
  112. func sortResources(ms pmetric.Metrics) {
  113. ms.ResourceMetrics().Sort(func(a, b pmetric.ResourceMetrics) bool {
  114. return compareMaps(a.Resource().Attributes(), b.Resource().Attributes()) < 0
  115. })
  116. }
  117. func sortScopes(ms pmetric.Metrics) {
  118. for i := 0; i < ms.ResourceMetrics().Len(); i++ {
  119. rm := ms.ResourceMetrics().At(i)
  120. rm.ScopeMetrics().Sort(func(a, b pmetric.ScopeMetrics) bool {
  121. return compareMaps(a.Scope().Attributes(), b.Scope().Attributes()) < 0
  122. })
  123. }
  124. }
  125. func sortNumberDataPointSlice(ndps pmetric.NumberDataPointSlice) {
  126. ndps.Sort(func(a, b pmetric.NumberDataPoint) bool {
  127. return compareMaps(a.Attributes(), b.Attributes()) < 0
  128. })
  129. }
  130. func sortSummaryDataPointSlice(sdps pmetric.SummaryDataPointSlice) {
  131. sdps.Sort(func(a, b pmetric.SummaryDataPoint) bool {
  132. return compareMaps(a.Attributes(), b.Attributes()) < 0
  133. })
  134. }
  135. func sortHistogramDataPointSlice(hdps pmetric.HistogramDataPointSlice) {
  136. hdps.Sort(func(a, b pmetric.HistogramDataPoint) bool {
  137. return compareMaps(a.Attributes(), b.Attributes()) < 0
  138. })
  139. }
  140. func sortExponentialHistogramDataPointSlice(ehdps pmetric.ExponentialHistogramDataPointSlice) {
  141. ehdps.Sort(func(a, b pmetric.ExponentialHistogramDataPoint) bool {
  142. return compareMaps(a.Attributes(), b.Attributes()) < 0
  143. })
  144. }
  145. func compareMaps(a, b pcommon.Map) int {
  146. sortAttributeMap(a)
  147. sortAttributeMap(b)
  148. if a.Len() != b.Len() {
  149. return a.Len() - b.Len()
  150. }
  151. var aKeys, bKeys []string
  152. a.Range(func(k string, v pcommon.Value) bool {
  153. aKeys = append(aKeys, fmt.Sprintf("%s: %v", k, v.AsString()))
  154. return true
  155. })
  156. b.Range(func(k string, v pcommon.Value) bool {
  157. bKeys = append(bKeys, fmt.Sprintf("%s: %v", k, v.AsString()))
  158. return true
  159. })
  160. for i := 0; i < len(aKeys); i++ {
  161. if aKeys[i] != bKeys[i] {
  162. return strings.Compare(aKeys[i], bKeys[i])
  163. }
  164. }
  165. return 0
  166. }