metrics_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. //go:build !windows
  4. // +build !windows
  5. package podmanreceiver
  6. import (
  7. "fmt"
  8. "testing"
  9. "time"
  10. "github.com/stretchr/testify/assert"
  11. "go.opentelemetry.io/collector/pdata/pmetric"
  12. )
  13. func TestTranslateStatsToMetrics(t *testing.T) {
  14. ts := time.Now()
  15. stats := genContainerStats()
  16. md := containerStatsToMetrics(ts, container{Image: "localimage"}, stats)
  17. assertStatsEqualToMetrics(t, stats, md)
  18. }
  19. func assertStatsEqualToMetrics(t *testing.T, podmanStats *containerStats, md pmetric.Metrics) {
  20. assert.Equal(t, md.ResourceMetrics().Len(), 1)
  21. rsm := md.ResourceMetrics().At(0)
  22. resourceAttrs := map[string]string{
  23. "container.runtime": "podman",
  24. "container.id": "abcd1234",
  25. "container.name": "cntrA",
  26. "container.image.name": "localimage",
  27. }
  28. for k, v := range resourceAttrs {
  29. attr, exists := rsm.Resource().Attributes().Get(k)
  30. assert.True(t, exists)
  31. assert.Equal(t, attr.Str(), v)
  32. }
  33. assert.Equal(t, rsm.ScopeMetrics().Len(), 1)
  34. metrics := rsm.ScopeMetrics().At(0).Metrics()
  35. assert.Equal(t, metrics.Len(), 11)
  36. for i := 0; i < metrics.Len(); i++ {
  37. m := metrics.At(i)
  38. switch m.Name() {
  39. case "container.memory.usage.limit":
  40. assertMetricEqual(t, m, pmetric.MetricTypeGauge, []point{{intVal: podmanStats.MemLimit}})
  41. case "container.memory.usage.total":
  42. assertMetricEqual(t, m, pmetric.MetricTypeGauge, []point{{intVal: podmanStats.MemUsage}})
  43. case "container.memory.percent":
  44. assertMetricEqual(t, m, pmetric.MetricTypeGauge, []point{{doubleVal: podmanStats.MemPerc}})
  45. case "container.network.io.usage.tx_bytes":
  46. assertMetricEqual(t, m, pmetric.MetricTypeSum, []point{{intVal: podmanStats.NetInput}})
  47. case "container.network.io.usage.rx_bytes":
  48. assertMetricEqual(t, m, pmetric.MetricTypeSum, []point{{intVal: podmanStats.NetOutput}})
  49. case "container.blockio.io_service_bytes_recursive.write":
  50. assertMetricEqual(t, m, pmetric.MetricTypeSum, []point{{intVal: podmanStats.BlockOutput}})
  51. case "container.blockio.io_service_bytes_recursive.read":
  52. assertMetricEqual(t, m, pmetric.MetricTypeSum, []point{{intVal: podmanStats.BlockInput}})
  53. case "container.cpu.usage.system":
  54. assertMetricEqual(t, m, pmetric.MetricTypeSum, []point{{intVal: podmanStats.CPUSystemNano}})
  55. case "container.cpu.usage.total":
  56. assertMetricEqual(t, m, pmetric.MetricTypeSum, []point{{intVal: podmanStats.CPUNano}})
  57. case "container.cpu.percent":
  58. assertMetricEqual(t, m, pmetric.MetricTypeGauge, []point{{doubleVal: podmanStats.CPU}})
  59. case "container.cpu.usage.percpu":
  60. points := make([]point, len(podmanStats.PerCPU))
  61. for i, v := range podmanStats.PerCPU {
  62. points[i] = point{intVal: v, attributes: map[string]string{"core": fmt.Sprintf("cpu%d", i)}}
  63. }
  64. assertMetricEqual(t, m, pmetric.MetricTypeSum, points)
  65. default:
  66. t.Errorf(fmt.Sprintf("unexpected metric: %s", m.Name()))
  67. }
  68. }
  69. }
  70. func assertMetricEqual(t *testing.T, m pmetric.Metric, dt pmetric.MetricType, pts []point) {
  71. assert.Equal(t, m.Type(), dt)
  72. switch dt {
  73. case pmetric.MetricTypeGauge:
  74. assertPoints(t, m.Gauge().DataPoints(), pts)
  75. case pmetric.MetricTypeSum:
  76. assertPoints(t, m.Sum().DataPoints(), pts)
  77. case pmetric.MetricTypeEmpty:
  78. t.Errorf("unexpected data type: %s", dt)
  79. case pmetric.MetricTypeHistogram:
  80. t.Errorf("unexpected data type: %s", dt)
  81. case pmetric.MetricTypeExponentialHistogram:
  82. t.Errorf("unexpected data type: %s", dt)
  83. case pmetric.MetricTypeSummary:
  84. t.Errorf("unexpected data type: %s", dt)
  85. default:
  86. t.Errorf("unexpected data type: %s", dt)
  87. }
  88. }
  89. func assertPoints(t *testing.T, dpts pmetric.NumberDataPointSlice, pts []point) {
  90. assert.Equal(t, dpts.Len(), len(pts))
  91. for i, expected := range pts {
  92. got := dpts.At(i)
  93. assert.Equal(t, got.IntValue(), int64(expected.intVal))
  94. assert.Equal(t, got.DoubleValue(), expected.doubleVal)
  95. for k, expectedV := range expected.attributes {
  96. gotV, exists := got.Attributes().Get(k)
  97. assert.True(t, exists)
  98. assert.Equal(t, gotV.Str(), expectedV)
  99. }
  100. }
  101. }
  102. func genContainerStats() *containerStats {
  103. return &containerStats{
  104. ContainerID: "abcd1234",
  105. Name: "cntrA",
  106. PerCPU: []uint64{40, 50, 20, 15},
  107. CPU: 78.67,
  108. CPUNano: 3451990,
  109. CPUSystemNano: 4573681,
  110. SystemNano: 3493456,
  111. MemUsage: 87,
  112. MemLimit: 200,
  113. MemPerc: 43.5,
  114. NetInput: 349323,
  115. NetOutput: 762442,
  116. BlockInput: 943894,
  117. BlockOutput: 324234,
  118. PIDs: 3,
  119. }
  120. }