Skip to content

Commit 16632ac

Browse files
committed
fixup unit tests
1 parent d75aab3 commit 16632ac

File tree

2 files changed

+272
-4
lines changed

2 files changed

+272
-4
lines changed

plugins/outputs/cloudwatch/cloudwatch_test.go

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ import (
2121
"github.com/aws/aws-sdk-go/aws/session"
2222
"github.com/influxdata/telegraf"
2323
"github.com/influxdata/telegraf/metric"
24+
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/aws/cloudwatch/histograms"
2425
"github.com/stretchr/testify/assert"
2526
"github.com/stretchr/testify/mock"
2627
"github.com/stretchr/testify/require"
2728
"go.opentelemetry.io/collector/component"
29+
"go.opentelemetry.io/collector/pdata/pcommon"
30+
"go.opentelemetry.io/collector/pdata/pmetric"
2831
"go.uber.org/zap"
2932

3033
"github.com/aws/amazon-cloudwatch-agent/extension/agenthealth/handler/useragent"
@@ -778,3 +781,270 @@ func TestUserAgentFeatureFlags(t *testing.T) {
778781
})
779782
}
780783
}
784+
785+
func TestBuildMetricDatumHist(t *testing.T) {
786+
testCases := histograms.TestCases()
787+
788+
for _, tc := range testCases {
789+
t.Run(tc.Name, func(t *testing.T) {
790+
// Create CloudWatch client
791+
svc := new(mockCloudWatchClient)
792+
cw := newCloudWatchClient(svc, time.Second)
793+
cw.config.MaxValuesPerDatum = 150
794+
795+
// Create histogram datapoint from test case
796+
dp := createHistogramDataPoint(tc.Input)
797+
798+
// Create aggregation datum
799+
metric := &aggregationDatum{
800+
MetricDatum: cloudwatch.MetricDatum{
801+
MetricName: aws.String("test_histogram"),
802+
Unit: aws.String("ms"),
803+
Timestamp: aws.Time(time.Now()),
804+
StorageResolution: aws.Int64(60),
805+
},
806+
histogram: &dp,
807+
}
808+
809+
// Create dimensions list
810+
dimensions := []*cloudwatch.Dimension{
811+
{Name: aws.String("service"), Value: aws.String("test")},
812+
}
813+
dimensionsList := [][]*cloudwatch.Dimension{dimensions}
814+
815+
// Call buildMetricDatumHist
816+
datums := cw.buildMetricDatumHist(metric, dimensionsList)
817+
818+
// Verify results
819+
assert.NotEmpty(t, datums, "Should produce at least one datum")
820+
821+
// Verify all datums have required fields
822+
totalCount := uint64(0)
823+
for i, datum := range datums {
824+
assert.NotNil(t, datum.MetricName)
825+
assert.Equal(t, "test_histogram", *datum.MetricName)
826+
assert.NotNil(t, datum.Unit)
827+
assert.Equal(t, "ms", *datum.Unit)
828+
assert.NotNil(t, datum.Timestamp)
829+
assert.NotNil(t, datum.StorageResolution)
830+
assert.Equal(t, int64(60), *datum.StorageResolution)
831+
assert.NotNil(t, datum.Dimensions)
832+
assert.NotNil(t, datum.StatisticValues)
833+
assert.NotNil(t, datum.Values)
834+
assert.NotNil(t, datum.Counts)
835+
836+
// Verify values and counts have same length
837+
assert.Equal(t, len(datum.Values), len(datum.Counts))
838+
assert.LessOrEqual(t, len(datum.Values), cw.config.MaxValuesPerDatum)
839+
840+
// Verify statistic values
841+
if i == 0 {
842+
// Sum is only assigned on the first datum
843+
assert.NotNil(t, datum.StatisticValues.Sum)
844+
assert.InDelta(t, tc.Expected.Sum, *datum.StatisticValues.Sum, 0.01)
845+
} else {
846+
assert.NotNil(t, datum.StatisticValues.Sum)
847+
assert.Zero(t, *datum.StatisticValues.Sum)
848+
}
849+
// Count can vary based on splitting
850+
totalCount += uint64(*datum.StatisticValues.SampleCount)
851+
if tc.Expected.Min != nil {
852+
assert.InDelta(t, *tc.Expected.Min, *datum.StatisticValues.Minimum, 0.01)
853+
}
854+
if tc.Expected.Max != nil {
855+
assert.InDelta(t, *tc.Expected.Max, *datum.StatisticValues.Maximum, 0.01)
856+
}
857+
}
858+
assert.Equal(t, tc.Expected.Count, totalCount)
859+
})
860+
}
861+
}
862+
863+
func TestBuildMetricDatumHistEmptyHistogram(t *testing.T) {
864+
svc := new(mockCloudWatchClient)
865+
cw := newCloudWatchClient(svc, time.Second)
866+
867+
// Create empty histogram
868+
dp := pmetric.NewHistogramDataPoint()
869+
dp.SetCount(0)
870+
dp.SetSum(0)
871+
dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
872+
873+
metric := &aggregationDatum{
874+
MetricDatum: cloudwatch.MetricDatum{
875+
MetricName: aws.String("empty_histogram"),
876+
},
877+
histogram: &dp,
878+
}
879+
880+
dimensions := [][]*cloudwatch.Dimension{{}}
881+
datums := cw.buildMetricDatumHist(metric, dimensions)
882+
883+
assert.Empty(t, datums, "Empty histogram should produce no datums")
884+
}
885+
886+
func TestBuildMetricDatumHistMaxValuesPerDatum(t *testing.T) {
887+
svc := new(mockCloudWatchClient)
888+
cw := newCloudWatchClient(svc, time.Second)
889+
cw.config.MaxValuesPerDatum = 10 // Small limit to test splitting
890+
891+
// Create histogram with many buckets
892+
input := histograms.HistogramInput{
893+
Count: 220, // 22 buckets * 10 items each
894+
Sum: 11000,
895+
Min: aws.Float64(5.0),
896+
Max: aws.Float64(225.0),
897+
Boundaries: make([]float64, 21),
898+
Counts: make([]uint64, 22),
899+
}
900+
901+
for i := 0; i < 21; i++ {
902+
input.Boundaries[i] = float64(i+1) * 10
903+
input.Counts[i] = 10
904+
}
905+
input.Counts[21] = 10
906+
907+
dp := createHistogramDataPoint(input)
908+
909+
metric := &aggregationDatum{
910+
MetricDatum: cloudwatch.MetricDatum{
911+
MetricName: aws.String("large_histogram"),
912+
},
913+
histogram: &dp,
914+
}
915+
916+
dimensions := [][]*cloudwatch.Dimension{{}}
917+
datums := cw.buildMetricDatumHist(metric, dimensions)
918+
919+
// Should split into multiple datums due to MaxValuesPerDatum limit
920+
assert.Greater(t, len(datums), 1, "Large histogram should be split into multiple datums")
921+
922+
// Verify each datum respects the limit
923+
for _, datum := range datums {
924+
assert.LessOrEqual(t, len(datum.Values), cw.config.MaxValuesPerDatum)
925+
assert.LessOrEqual(t, len(datum.Counts), cw.config.MaxValuesPerDatum)
926+
}
927+
928+
// Verify only first datum has sum
929+
assert.Greater(t, *datums[0].StatisticValues.Sum, 0.0)
930+
for i := 1; i < len(datums); i++ {
931+
assert.Zero(t, *datums[i].StatisticValues.Sum)
932+
}
933+
}
934+
935+
func TestBuildMetricDatumHistDropOriginalMetrics(t *testing.T) {
936+
svc := new(mockCloudWatchClient)
937+
cw := newCloudWatchClient(svc, time.Second)
938+
cw.config.DropOriginalConfigs = map[string]bool{
939+
"dropped_histogram": true,
940+
}
941+
942+
// Create test histogram
943+
input := histograms.HistogramInput{
944+
Count: 100,
945+
Sum: 5000,
946+
Min: aws.Float64(10.0),
947+
Max: aws.Float64(200.0),
948+
Boundaries: []float64{25, 50, 75, 100, 150},
949+
Counts: []uint64{20, 30, 25, 15, 8, 2},
950+
}
951+
952+
dp := createHistogramDataPoint(input)
953+
954+
metric := &aggregationDatum{
955+
MetricDatum: cloudwatch.MetricDatum{
956+
MetricName: aws.String("dropped_histogram"),
957+
},
958+
histogram: &dp,
959+
}
960+
961+
// First dimension set (index 0) should be dropped
962+
dimensions := [][]*cloudwatch.Dimension{
963+
{{Name: aws.String("original"), Value: aws.String("true")}},
964+
{{Name: aws.String("rollup"), Value: aws.String("true")}},
965+
}
966+
967+
datums := cw.buildMetricDatumHist(metric, dimensions)
968+
969+
// Should only have datums for rollup dimensions (not original)
970+
assert.Equal(t, 1, len(datums))
971+
assert.Equal(t, "true", *datums[0].Dimensions[0].Value)
972+
}
973+
974+
func TestBuildMetricDatumHistMultipleDimensions(t *testing.T) {
975+
svc := new(mockCloudWatchClient)
976+
cw := newCloudWatchClient(svc, time.Second)
977+
978+
// Create test histogram
979+
input := histograms.HistogramInput{
980+
Count: 50,
981+
Sum: 2500,
982+
Min: aws.Float64(10.0),
983+
Max: aws.Float64(100.0),
984+
Boundaries: []float64{25, 50, 75},
985+
Counts: []uint64{10, 15, 15, 10},
986+
}
987+
988+
dp := createHistogramDataPoint(input)
989+
990+
metric := &aggregationDatum{
991+
MetricDatum: cloudwatch.MetricDatum{
992+
MetricName: aws.String("multi_dim_histogram"),
993+
},
994+
histogram: &dp,
995+
}
996+
997+
// Multiple dimension sets
998+
dimensions := [][]*cloudwatch.Dimension{
999+
{{Name: aws.String("service"), Value: aws.String("api")}},
1000+
{{Name: aws.String("service"), Value: aws.String("api")}, {Name: aws.String("env"), Value: aws.String("prod")}},
1001+
{},
1002+
}
1003+
1004+
datums := cw.buildMetricDatumHist(metric, dimensions)
1005+
1006+
// Should have one datum per dimension set
1007+
assert.Equal(t, 3, len(datums))
1008+
1009+
// Verify dimensions
1010+
assert.Equal(t, 1, len(datums[0].Dimensions))
1011+
assert.Equal(t, 2, len(datums[1].Dimensions))
1012+
assert.Equal(t, 0, len(datums[2].Dimensions))
1013+
}
1014+
1015+
// Helper function to create histogram datapoint from test input
1016+
func createHistogramDataPoint(input histograms.HistogramInput) pmetric.HistogramDataPoint {
1017+
dp := pmetric.NewHistogramDataPoint()
1018+
dp.SetCount(input.Count)
1019+
dp.SetSum(input.Sum)
1020+
dp.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
1021+
1022+
if input.Min != nil {
1023+
dp.SetMin(*input.Min)
1024+
}
1025+
if input.Max != nil {
1026+
dp.SetMax(*input.Max)
1027+
}
1028+
1029+
// Set boundaries
1030+
bounds := dp.ExplicitBounds()
1031+
bounds.EnsureCapacity(len(input.Boundaries))
1032+
for _, boundary := range input.Boundaries {
1033+
bounds.Append(boundary)
1034+
}
1035+
1036+
// Set bucket counts
1037+
bucketCounts := dp.BucketCounts()
1038+
bucketCounts.EnsureCapacity(len(input.Counts))
1039+
for _, count := range input.Counts {
1040+
bucketCounts.Append(count)
1041+
}
1042+
1043+
// Set attributes
1044+
attrs := dp.Attributes()
1045+
for k, v := range input.Attributes {
1046+
attrs.PutStr(k, v)
1047+
}
1048+
1049+
return dp
1050+
}

plugins/outputs/cloudwatch/convert_otel_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,8 @@ func createTestHistogram(
116116
for j := 0; j < numDatapoints; j++ {
117117
dp := m.Histogram().DataPoints().AppendEmpty()
118118
// Make the values match the count so it is easy to verify.
119-
dp.ExplicitBounds().Append(float64(1 + i))
120-
dp.ExplicitBounds().Append(float64(2 + 2*i))
121-
dp.BucketCounts().Append(uint64(1 + i))
122-
dp.BucketCounts().Append(uint64(2 + 2*i))
119+
dp.ExplicitBounds().FromRaw([]float64{5, 10})
120+
dp.BucketCounts().FromRaw([]uint64{600, 10, 387})
123121
dp.SetMax(histogramMax)
124122
dp.SetMin(histogramMin)
125123
dp.SetSum(histogramSum)

0 commit comments

Comments
 (0)