2021-10-22 05:32:10 +08:00
|
|
|
package timestream
|
2020-10-16 01:51:17 +08:00
|
|
|
|
|
|
|
|
import (
|
2021-10-22 05:32:10 +08:00
|
|
|
"context"
|
2020-10-16 01:51:17 +08:00
|
|
|
"fmt"
|
|
|
|
|
"reflect"
|
|
|
|
|
"sort"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
|
|
|
"github.com/aws/aws-sdk-go-v2/service/timestreamwrite"
|
|
|
|
|
"github.com/aws/aws-sdk-go-v2/service/timestreamwrite/types"
|
2021-11-25 03:33:45 +08:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
2020-10-16 01:51:17 +08:00
|
|
|
"github.com/influxdata/telegraf"
|
|
|
|
|
internalaws "github.com/influxdata/telegraf/config/aws"
|
|
|
|
|
"github.com/influxdata/telegraf/testutil"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const tsDbName = "testDb"
|
|
|
|
|
|
|
|
|
|
const testSingleTableName = "SingleTableName"
|
|
|
|
|
const testSingleTableDim = "namespace"
|
|
|
|
|
|
|
|
|
|
var time1 = time.Date(2009, time.November, 10, 22, 0, 0, 0, time.UTC)
|
|
|
|
|
|
|
|
|
|
const time1Epoch = "1257890400"
|
2022-01-07 06:28:23 +08:00
|
|
|
const timeUnit = types.TimeUnitSeconds
|
2020-10-16 01:51:17 +08:00
|
|
|
|
|
|
|
|
var time2 = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
|
|
|
|
|
|
|
|
|
|
const time2Epoch = "1257894000"
|
|
|
|
|
|
|
|
|
|
const metricName1 = "metricName1"
|
|
|
|
|
const metricName2 = "metricName2"
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
type mockTimestreamClient struct{}
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
func (m *mockTimestreamClient) CreateTable(context.Context, *timestreamwrite.CreateTableInput, ...func(*timestreamwrite.Options)) (*timestreamwrite.CreateTableOutput, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return nil, nil
|
|
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
func (m *mockTimestreamClient) WriteRecords(context.Context, *timestreamwrite.WriteRecordsInput, ...func(*timestreamwrite.Options)) (*timestreamwrite.WriteRecordsOutput, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return nil, nil
|
|
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
func (m *mockTimestreamClient) DescribeDatabase(context.Context, *timestreamwrite.DescribeDatabaseInput, ...func(*timestreamwrite.Options)) (*timestreamwrite.DescribeDatabaseOutput, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return nil, fmt.Errorf("hello from DescribeDatabase")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestConnectValidatesConfigParameters(t *testing.T) {
|
2021-10-22 05:32:10 +08:00
|
|
|
WriteFactory = func(credentialConfig *internalaws.CredentialConfig) (WriteClient, error) {
|
2021-10-08 04:47:56 +08:00
|
|
|
return &mockTimestreamClient{}, nil
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
|
|
|
|
// checking base arguments
|
2021-10-22 05:32:10 +08:00
|
|
|
noDatabaseName := Timestream{Log: testutil.Logger{}}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, noDatabaseName.Connect().Error(), "DatabaseName")
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
noMappingMode := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, noMappingMode.Connect().Error(), "MappingMode")
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
incorrectMappingMode := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
|
|
|
|
MappingMode: "foo",
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, incorrectMappingMode.Connect().Error(), "single-table")
|
2020-10-16 01:51:17 +08:00
|
|
|
|
|
|
|
|
// multi-table arguments
|
2021-10-22 05:32:10 +08:00
|
|
|
validMappingModeMultiTable := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Nil(t, validMappingModeMultiTable.Connect())
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
singleTableNameWithMultiTable := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
SingleTableName: testSingleTableName,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, singleTableNameWithMultiTable.Connect().Error(), "SingleTableName")
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
singleTableDimensionWithMultiTable := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
SingleTableDimensionNameForTelegrafMeasurementName: testSingleTableDim,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, singleTableDimensionWithMultiTable.Connect().Error(),
|
2020-10-16 01:51:17 +08:00
|
|
|
"SingleTableDimensionNameForTelegrafMeasurementName")
|
|
|
|
|
|
|
|
|
|
// single-table arguments
|
2021-10-22 05:32:10 +08:00
|
|
|
noTableNameMappingModeSingleTable := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, noTableNameMappingModeSingleTable.Connect().Error(), "SingleTableName")
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
noDimensionNameMappingModeSingleTable := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
SingleTableName: testSingleTableName,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, noDimensionNameMappingModeSingleTable.Connect().Error(),
|
2020-10-16 01:51:17 +08:00
|
|
|
"SingleTableDimensionNameForTelegrafMeasurementName")
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
validConfigurationMappingModeSingleTable := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
SingleTableName: testSingleTableName,
|
|
|
|
|
SingleTableDimensionNameForTelegrafMeasurementName: testSingleTableDim,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Nil(t, validConfigurationMappingModeSingleTable.Connect())
|
2020-10-16 01:51:17 +08:00
|
|
|
|
|
|
|
|
// create table arguments
|
2021-10-22 05:32:10 +08:00
|
|
|
createTableNoMagneticRetention := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
CreateTableIfNotExists: true,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, createTableNoMagneticRetention.Connect().Error(),
|
2020-10-16 01:51:17 +08:00
|
|
|
"CreateTableMagneticStoreRetentionPeriodInDays")
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
createTableNoMemoryRetention := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
CreateTableIfNotExists: true,
|
|
|
|
|
CreateTableMagneticStoreRetentionPeriodInDays: 3,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, createTableNoMemoryRetention.Connect().Error(),
|
2020-10-16 01:51:17 +08:00
|
|
|
"CreateTableMemoryStoreRetentionPeriodInHours")
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
createTableValid := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
CreateTableIfNotExists: true,
|
|
|
|
|
CreateTableMagneticStoreRetentionPeriodInDays: 3,
|
|
|
|
|
CreateTableMemoryStoreRetentionPeriodInHours: 3,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Nil(t, createTableValid.Connect())
|
2020-10-16 01:51:17 +08:00
|
|
|
|
|
|
|
|
// describe table on start arguments
|
2021-10-22 05:32:10 +08:00
|
|
|
describeTableInvoked := Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
2021-10-22 05:32:10 +08:00
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
DescribeDatabaseOnStart: true,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Contains(t, describeTableInvoked.Connect().Error(), "hello from DescribeDatabase")
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type mockTimestreamErrorClient struct {
|
|
|
|
|
ErrorToReturnOnWriteRecords error
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
func (m *mockTimestreamErrorClient) CreateTable(context.Context, *timestreamwrite.CreateTableInput, ...func(*timestreamwrite.Options)) (*timestreamwrite.CreateTableOutput, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return nil, nil
|
|
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
func (m *mockTimestreamErrorClient) WriteRecords(context.Context, *timestreamwrite.WriteRecordsInput, ...func(*timestreamwrite.Options)) (*timestreamwrite.WriteRecordsOutput, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return nil, m.ErrorToReturnOnWriteRecords
|
|
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
func (m *mockTimestreamErrorClient) DescribeDatabase(context.Context, *timestreamwrite.DescribeDatabaseInput, ...func(*timestreamwrite.Options)) (*timestreamwrite.DescribeDatabaseOutput, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestThrottlingErrorIsReturnedToTelegraf(t *testing.T) {
|
2021-10-22 05:32:10 +08:00
|
|
|
WriteFactory = func(credentialConfig *internalaws.CredentialConfig) (WriteClient, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return &mockTimestreamErrorClient{
|
2021-10-22 05:32:10 +08:00
|
|
|
ErrorToReturnOnWriteRecords: &types.ThrottlingException{Message: aws.String("Throttling Test")},
|
2021-10-08 04:47:56 +08:00
|
|
|
}, nil
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
|
|
|
|
|
plugin := Timestream{
|
|
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.NoError(t, plugin.Connect())
|
2020-10-16 01:51:17 +08:00
|
|
|
input := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{"value": float64(1)},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
err := plugin.Write([]telegraf.Metric{input})
|
|
|
|
|
|
2021-11-25 03:33:45 +08:00
|
|
|
require.NotNil(t, err, "Expected an error to be returned to Telegraf, "+
|
2020-10-16 01:51:17 +08:00
|
|
|
"so that the write will be retried by Telegraf later.")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRejectedRecordsErrorResultsInMetricsBeingSkipped(t *testing.T) {
|
2021-10-22 05:32:10 +08:00
|
|
|
WriteFactory = func(credentialConfig *internalaws.CredentialConfig) (WriteClient, error) {
|
2020-10-16 01:51:17 +08:00
|
|
|
return &mockTimestreamErrorClient{
|
2021-10-22 05:32:10 +08:00
|
|
|
ErrorToReturnOnWriteRecords: &types.RejectedRecordsException{Message: aws.String("RejectedRecords Test")},
|
2021-10-08 04:47:56 +08:00
|
|
|
}, nil
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
|
|
|
|
|
plugin := Timestream{
|
|
|
|
|
MappingMode: MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
DatabaseName: tsDbName,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-11-25 03:33:45 +08:00
|
|
|
require.NoError(t, plugin.Connect())
|
2020-10-16 01:51:17 +08:00
|
|
|
input := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{"value": float64(1)},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
err := plugin.Write([]telegraf.Metric{input})
|
|
|
|
|
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Nil(t, err, "Expected to silently swallow the RejectedRecordsException, "+
|
2020-10-16 01:51:17 +08:00
|
|
|
"as retrying this error doesn't make sense.")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsSkipEmptyMetric(t *testing.T) {
|
|
|
|
|
input1 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{}, //no fields here
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
input2 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag2": "value2"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value": float64(10),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
input3 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{}, //record with no dimensions should appear in the results
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value": float64(20),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
records := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag2": "value2", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value": "10"},
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value": "20"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
|
|
|
|
|
expectedResultSingleTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(testSingleTableName),
|
|
|
|
|
Records: records,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2, input3},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
recordsMulti := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag2": "value2"},
|
|
|
|
|
measureValues: map[string]string{"value": "10"},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{},
|
|
|
|
|
measureValues: map[string]string{"value": "20"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
|
|
|
|
|
expectedResultMultiTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(metricName1),
|
|
|
|
|
Records: recordsMulti,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2, input3},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultMultiTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsRequestsAboveLimitAreSplit(t *testing.T) {
|
|
|
|
|
const maxRecordsInWriteRecordsCall = 100
|
|
|
|
|
|
|
|
|
|
var inputs []telegraf.Metric
|
|
|
|
|
for i := 1; i <= maxRecordsInWriteRecordsCall+1; i++ {
|
|
|
|
|
fieldName := "value_supported" + strconv.Itoa(i)
|
|
|
|
|
inputs = append(inputs, testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
fieldName: float64(10),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resultFields := make(map[string]string)
|
|
|
|
|
for i := 1; i <= maxRecordsInWriteRecordsCall; i++ {
|
|
|
|
|
fieldName := "value_supported" + strconv.Itoa(i)
|
|
|
|
|
resultFields[fieldName] = "10"
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult1SingleTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: resultFields,
|
|
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult2SingleTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported" + strconv.Itoa(maxRecordsInWriteRecordsCall+1): "10"},
|
|
|
|
|
})
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
inputs,
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResult1SingleTable, expectedResult2SingleTable})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult1MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: resultFields,
|
|
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult2MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported" + strconv.Itoa(maxRecordsInWriteRecordsCall+1): "10"},
|
|
|
|
|
})
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
inputs,
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResult1MultiTable, expectedResult2MultiTable})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsDifferentDimensionsSameTimestampsAreWrittenSeparate(t *testing.T) {
|
2022-01-07 06:28:23 +08:00
|
|
|
|
2020-10-16 01:51:17 +08:00
|
|
|
input1 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(10), "value_supported2": float64(20),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
2022-01-07 06:28:23 +08:00
|
|
|
|
2020-10-16 01:51:17 +08:00
|
|
|
input2 := testutil.MustMetric(
|
2022-01-07 06:28:23 +08:00
|
|
|
metricName2,
|
2020-10-16 01:51:17 +08:00
|
|
|
map[string]string{"tag2": "value2"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported3": float64(30),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
recordsSingle := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20"},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag2": "value2", testSingleTableDim: metricName2},
|
|
|
|
|
measureValues: map[string]string{"value_supported3": "30"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultSingleTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(testSingleTableName),
|
|
|
|
|
Records: recordsSingle,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult1MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20"},
|
|
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
|
|
|
|
|
expectedResult2MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
2022-01-07 06:28:23 +08:00
|
|
|
tableName: metricName2,
|
2020-10-16 01:51:17 +08:00
|
|
|
dimensions: map[string]string{"tag2": "value2"},
|
|
|
|
|
measureValues: map[string]string{"value_supported3": "30"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResult1MultiTable, expectedResult2MultiTable})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsSameDimensionsDifferentDimensionValuesAreWrittenSeparate(t *testing.T) {
|
|
|
|
|
input1 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(10),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
input2 := testutil.MustMetric(
|
2022-01-07 06:28:23 +08:00
|
|
|
metricName2,
|
2020-10-16 01:51:17 +08:00
|
|
|
map[string]string{"tag1": "value2"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(20),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
recordsSingle := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10"},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value2", testSingleTableDim: metricName2},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "20"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultSingleTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(testSingleTableName),
|
|
|
|
|
Records: recordsSingle,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult1MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10"},
|
|
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult2MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
2022-01-07 06:28:23 +08:00
|
|
|
tableName: metricName2,
|
2020-10-16 01:51:17 +08:00
|
|
|
dimensions: map[string]string{"tag1": "value2"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "20"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResult1MultiTable, expectedResult2MultiTable})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsSameDimensionsDifferentTimestampsAreWrittenSeparate(t *testing.T) {
|
|
|
|
|
input1 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(10), "value_supported2": float64(20),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
input2 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported3": float64(30),
|
|
|
|
|
},
|
|
|
|
|
time2,
|
|
|
|
|
)
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
recordsSingle := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20"},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
t: time2Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported3": "30"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultSingleTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(testSingleTableName),
|
|
|
|
|
Records: recordsSingle,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
recordsMultiTable := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20"},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
t: time2Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported3": "30"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultMultiTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(metricName1),
|
|
|
|
|
Records: recordsMultiTable,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultMultiTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsSameDimensionsSameTimestampsAreWrittenTogether(t *testing.T) {
|
|
|
|
|
input1 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(10), "value_supported2": float64(20),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
input2 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported3": float64(30),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultSingleTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20", "value_supported3": "30"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultMultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20", "value_supported3": "30"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultMultiTable})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsDifferentMetricsAreWrittenToDifferentTablesInMultiTableMapping(t *testing.T) {
|
|
|
|
|
input1 := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(10), "value_supported2": float64(20),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
input2 := testutil.MustMetric(
|
|
|
|
|
metricName2,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported3": float64(30),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
recordsSingle := buildRecords([]SimpleInput{
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20"},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName2},
|
|
|
|
|
measureValues: map[string]string{"value_supported3": "30"},
|
|
|
|
|
},
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultSingleTable := ×treamwrite.WriteRecordsInput{
|
|
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(testSingleTableName),
|
|
|
|
|
Records: recordsSingle,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
2022-01-07 06:28:23 +08:00
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
2020-10-16 01:51:17 +08:00
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult1MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10", "value_supported2": "20"},
|
|
|
|
|
})
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResult2MultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName2,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported3": "30"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{input1, input2},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResult1MultiTable, expectedResult2MultiTable})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTransformMetricsUnsupportedFieldsAreSkipped(t *testing.T) {
|
|
|
|
|
metricWithUnsupportedField := testutil.MustMetric(
|
|
|
|
|
metricName1,
|
|
|
|
|
map[string]string{"tag1": "value1"},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"value_supported1": float64(10), "value_unsupported": time.Now(),
|
|
|
|
|
},
|
|
|
|
|
time1,
|
|
|
|
|
)
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultSingleTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: testSingleTableName,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1", testSingleTableDim: metricName1},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeSingleTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{metricWithUnsupportedField},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultSingleTable})
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
expectedResultMultiTable := buildExpectedInput(SimpleInput{
|
2020-10-16 01:51:17 +08:00
|
|
|
t: time1Epoch,
|
|
|
|
|
tableName: metricName1,
|
|
|
|
|
dimensions: map[string]string{"tag1": "value1"},
|
|
|
|
|
measureValues: map[string]string{"value_supported1": "10"},
|
|
|
|
|
})
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
comparisonTest(t, MappingModeMultiTable,
|
2020-10-16 01:51:17 +08:00
|
|
|
[]telegraf.Metric{metricWithUnsupportedField},
|
|
|
|
|
[]*timestreamwrite.WriteRecordsInput{expectedResultMultiTable})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func comparisonTest(t *testing.T,
|
|
|
|
|
mappingMode string,
|
|
|
|
|
telegrafMetrics []telegraf.Metric,
|
2021-03-24 23:27:46 +08:00
|
|
|
timestreamRecords []*timestreamwrite.WriteRecordsInput,
|
|
|
|
|
) {
|
2021-10-22 05:32:10 +08:00
|
|
|
var plugin Timestream
|
2020-10-16 01:51:17 +08:00
|
|
|
switch mappingMode {
|
2021-10-22 05:32:10 +08:00
|
|
|
case MappingModeSingleTable:
|
|
|
|
|
plugin = Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
MappingMode: mappingMode,
|
|
|
|
|
DatabaseName: tsDbName,
|
|
|
|
|
|
|
|
|
|
SingleTableName: testSingleTableName,
|
|
|
|
|
SingleTableDimensionNameForTelegrafMeasurementName: testSingleTableDim,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
2021-10-22 05:32:10 +08:00
|
|
|
case MappingModeMultiTable:
|
|
|
|
|
plugin = Timestream{
|
2020-10-16 01:51:17 +08:00
|
|
|
MappingMode: mappingMode,
|
|
|
|
|
DatabaseName: tsDbName,
|
|
|
|
|
Log: testutil.Logger{},
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-07 06:28:23 +08:00
|
|
|
|
|
|
|
|
comparison(t, plugin, mappingMode, telegrafMetrics, timestreamRecords)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func comparison(t *testing.T,
|
|
|
|
|
plugin Timestream,
|
|
|
|
|
mappingMode string,
|
|
|
|
|
telegrafMetrics []telegraf.Metric,
|
|
|
|
|
timestreamRecords []*timestreamwrite.WriteRecordsInput) {
|
2020-10-16 01:51:17 +08:00
|
|
|
result := plugin.TransformMetrics(telegrafMetrics)
|
|
|
|
|
|
2021-11-25 03:33:45 +08:00
|
|
|
require.Equal(t, len(timestreamRecords), len(result), "The number of transformed records was expected to be different")
|
2020-10-16 01:51:17 +08:00
|
|
|
for _, tsRecord := range timestreamRecords {
|
2021-11-25 03:33:45 +08:00
|
|
|
require.True(t, arrayContains(result, tsRecord), "Expected that the list of requests to Timestream: \n%s\n\n "+
|
2020-10-16 01:51:17 +08:00
|
|
|
"will contain request: \n%s\n\nUsed MappingMode: %s", result, tsRecord, mappingMode)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func arrayContains(
|
|
|
|
|
array []*timestreamwrite.WriteRecordsInput,
|
2021-03-24 23:27:46 +08:00
|
|
|
element *timestreamwrite.WriteRecordsInput,
|
|
|
|
|
) bool {
|
2020-10-16 01:51:17 +08:00
|
|
|
sortWriteInputForComparison(*element)
|
|
|
|
|
|
|
|
|
|
for _, a := range array {
|
|
|
|
|
sortWriteInputForComparison(*a)
|
|
|
|
|
|
|
|
|
|
if reflect.DeepEqual(a, element) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func sortWriteInputForComparison(element timestreamwrite.WriteRecordsInput) {
|
|
|
|
|
// sort the records by MeasureName, as they are kept in an array, but the order of records doesn't matter
|
|
|
|
|
sort.Slice(element.Records, func(i, j int) bool {
|
|
|
|
|
return strings.Compare(*element.Records[i].MeasureName, *element.Records[j].MeasureName) < 0
|
|
|
|
|
})
|
|
|
|
|
// sort the dimensions in CommonAttributes
|
|
|
|
|
if element.CommonAttributes != nil {
|
|
|
|
|
sort.Slice(element.CommonAttributes.Dimensions, func(i, j int) bool {
|
|
|
|
|
return strings.Compare(*element.CommonAttributes.Dimensions[i].Name,
|
|
|
|
|
*element.CommonAttributes.Dimensions[j].Name) < 0
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// sort the dimensions in Records
|
|
|
|
|
for _, r := range element.Records {
|
|
|
|
|
sort.Slice(r.Dimensions, func(i, j int) bool {
|
|
|
|
|
return strings.Compare(*r.Dimensions[i].Name, *r.Dimensions[j].Name) < 0
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SimpleInput struct {
|
|
|
|
|
t string
|
|
|
|
|
tableName string
|
|
|
|
|
dimensions map[string]string
|
|
|
|
|
measureValues map[string]string
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-07 06:28:23 +08:00
|
|
|
func buildExpectedInput(i SimpleInput) *timestreamwrite.WriteRecordsInput {
|
2021-10-22 05:32:10 +08:00
|
|
|
var tsDimensions []types.Dimension
|
2020-10-16 01:51:17 +08:00
|
|
|
for k, v := range i.dimensions {
|
2021-10-22 05:32:10 +08:00
|
|
|
tsDimensions = append(tsDimensions, types.Dimension{
|
2020-10-16 01:51:17 +08:00
|
|
|
Name: aws.String(k),
|
|
|
|
|
Value: aws.String(v),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 05:32:10 +08:00
|
|
|
var tsRecords []types.Record
|
2020-10-16 01:51:17 +08:00
|
|
|
for k, v := range i.measureValues {
|
2021-10-22 05:32:10 +08:00
|
|
|
tsRecords = append(tsRecords, types.Record{
|
2020-10-16 01:51:17 +08:00
|
|
|
MeasureName: aws.String(k),
|
|
|
|
|
MeasureValue: aws.String(v),
|
2021-10-22 05:32:10 +08:00
|
|
|
MeasureValueType: types.MeasureValueTypeDouble,
|
2022-01-07 06:28:23 +08:00
|
|
|
Dimensions: tsDimensions,
|
|
|
|
|
Time: aws.String(i.t),
|
|
|
|
|
TimeUnit: timeUnit,
|
2020-10-16 01:51:17 +08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result := ×treamwrite.WriteRecordsInput{
|
2022-01-07 06:28:23 +08:00
|
|
|
DatabaseName: aws.String(tsDbName),
|
|
|
|
|
TableName: aws.String(i.tableName),
|
|
|
|
|
Records: tsRecords,
|
|
|
|
|
CommonAttributes: &types.Record{},
|
2020-10-16 01:51:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
}
|
2022-01-07 06:28:23 +08:00
|
|
|
|
|
|
|
|
func buildRecords(inputs []SimpleInput) []types.Record {
|
|
|
|
|
var tsRecords []types.Record
|
|
|
|
|
|
|
|
|
|
for _, inp := range inputs {
|
|
|
|
|
tsRecords = append(tsRecords, buildRecord(inp)...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tsRecords
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildRecord(input SimpleInput) []types.Record {
|
|
|
|
|
var tsRecords []types.Record
|
|
|
|
|
|
|
|
|
|
var tsDimensions []types.Dimension
|
|
|
|
|
|
|
|
|
|
for k, v := range input.dimensions {
|
|
|
|
|
tsDimensions = append(tsDimensions, types.Dimension{
|
|
|
|
|
Name: aws.String(k),
|
|
|
|
|
Value: aws.String(v),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for k, v := range input.measureValues {
|
|
|
|
|
tsRecords = append(tsRecords, types.Record{
|
|
|
|
|
MeasureName: aws.String(k),
|
|
|
|
|
MeasureValue: aws.String(v),
|
|
|
|
|
MeasureValueType: types.MeasureValueTypeDouble,
|
|
|
|
|
Dimensions: tsDimensions,
|
|
|
|
|
Time: aws.String(input.t),
|
|
|
|
|
TimeUnit: timeUnit,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tsRecords
|
|
|
|
|
}
|