219 lines
6.6 KiB
Go
219 lines
6.6 KiB
Go
package adx
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/Azure/azure-kusto-go/kusto"
|
|
"github.com/Azure/azure-kusto-go/kusto/ingest"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/influxdata/telegraf"
|
|
"github.com/influxdata/telegraf/config"
|
|
serializers_json "github.com/influxdata/telegraf/plugins/serializers/json"
|
|
"github.com/influxdata/telegraf/testutil"
|
|
)
|
|
|
|
func TestInitBlankEndpointData(t *testing.T) {
|
|
plugin := Config{
|
|
Endpoint: "",
|
|
Database: "mydb",
|
|
}
|
|
|
|
_, err := plugin.NewClient("TestKusto.Telegraf", nil)
|
|
require.Error(t, err)
|
|
require.Equal(t, "endpoint configuration cannot be empty", err.Error())
|
|
}
|
|
|
|
func TestQueryConstruction(t *testing.T) {
|
|
const tableName = "mytable"
|
|
const expectedCreate = `.create-merge table ['mytable'] (['fields']:dynamic, ['name']:string, ['tags']:dynamic, ['timestamp']:datetime);`
|
|
const expectedMapping = `` +
|
|
`.create-or-alter table ['mytable'] ingestion json mapping 'mytable_mapping' '[{"column":"fields", ` +
|
|
`"Properties":{"Path":"$[\'fields\']"}},{"column":"name", "Properties":{"Path":"$[\'name\']"}},{"column":"tags", ` +
|
|
`"Properties":{"Path":"$[\'tags\']"}},{"column":"timestamp", "Properties":{"Path":"$[\'timestamp\']"}}]'`
|
|
require.Equal(t, expectedCreate, createTableCommand(tableName).String())
|
|
require.Equal(t, expectedMapping, createTableMappingCommand(tableName).String())
|
|
}
|
|
|
|
func TestGetMetricIngestor(t *testing.T) {
|
|
plugin := Client{
|
|
logger: testutil.Logger{},
|
|
client: kusto.NewMockClient(),
|
|
cfg: &Config{
|
|
Database: "mydb",
|
|
IngestionType: QueuedIngestion,
|
|
},
|
|
ingestors: map[string]ingest.Ingestor{"test1": &fakeIngestor{}},
|
|
}
|
|
|
|
ingestor, err := plugin.getMetricIngestor(t.Context(), "test1")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, ingestor)
|
|
}
|
|
|
|
func TestGetMetricIngestorNoIngester(t *testing.T) {
|
|
plugin := Client{
|
|
logger: testutil.Logger{},
|
|
client: kusto.NewMockClient(),
|
|
cfg: &Config{
|
|
IngestionType: QueuedIngestion,
|
|
},
|
|
ingestors: map[string]ingest.Ingestor{"test1": &fakeIngestor{}},
|
|
}
|
|
|
|
ingestor, err := plugin.getMetricIngestor(t.Context(), "test1")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, ingestor)
|
|
}
|
|
|
|
func TestPushMetrics(t *testing.T) {
|
|
plugin := Client{
|
|
logger: testutil.Logger{},
|
|
client: kusto.NewMockClient(),
|
|
cfg: &Config{
|
|
Database: "mydb",
|
|
Endpoint: "https://ingest-test.westus.kusto.windows.net",
|
|
IngestionType: QueuedIngestion,
|
|
},
|
|
ingestors: map[string]ingest.Ingestor{"test1": &fakeIngestor{}},
|
|
}
|
|
|
|
metrics := []byte(`{"fields": {"value": 1}, "name": "test1", "tags": {"tag1": "value1"}, "timestamp": "2021-01-01T00:00:00Z"}`)
|
|
require.NoError(t, plugin.PushMetrics(ingest.FileFormat(ingest.JSON), "test1", metrics))
|
|
}
|
|
|
|
func TestPushMetricsOutputs(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
inputMetric []telegraf.Metric
|
|
metricsGrouping string
|
|
createTables bool
|
|
ingestionType string
|
|
}{
|
|
{
|
|
name: "Valid metric",
|
|
inputMetric: testutil.MockMetrics(),
|
|
createTables: true,
|
|
metricsGrouping: TablePerMetric,
|
|
},
|
|
{
|
|
name: "Don't create tables'",
|
|
inputMetric: testutil.MockMetrics(),
|
|
createTables: false,
|
|
metricsGrouping: TablePerMetric,
|
|
},
|
|
{
|
|
name: "SingleTable metric grouping type",
|
|
inputMetric: testutil.MockMetrics(),
|
|
createTables: true,
|
|
metricsGrouping: SingleTable,
|
|
},
|
|
{
|
|
name: "Valid metric managed ingestion",
|
|
inputMetric: testutil.MockMetrics(),
|
|
createTables: true,
|
|
metricsGrouping: TablePerMetric,
|
|
ingestionType: ManagedIngestion,
|
|
},
|
|
}
|
|
var expectedMetric = map[string]interface{}{
|
|
"metricName": "test1",
|
|
"fields": map[string]interface{}{
|
|
"value": 1.0,
|
|
},
|
|
"tags": map[string]interface{}{
|
|
"tag1": "value1",
|
|
},
|
|
"timestamp": float64(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).UnixNano() / int64(time.Second)),
|
|
}
|
|
for _, tC := range testCases {
|
|
t.Run(tC.name, func(t *testing.T) {
|
|
ingestionType := "queued"
|
|
if tC.ingestionType != "" {
|
|
ingestionType = tC.ingestionType
|
|
}
|
|
|
|
serializer := &serializers_json.Serializer{
|
|
TimestampUnits: config.Duration(time.Nanosecond),
|
|
TimestampFormat: time.RFC3339Nano,
|
|
}
|
|
|
|
cfg := &Config{
|
|
Endpoint: "https://someendpoint.kusto.net",
|
|
Database: "databasename",
|
|
MetricsGrouping: tC.metricsGrouping,
|
|
TableName: "test1",
|
|
CreateTables: tC.createTables,
|
|
IngestionType: ingestionType,
|
|
Timeout: config.Duration(20 * time.Second),
|
|
}
|
|
client, err := cfg.NewClient("telegraf", &testutil.Logger{})
|
|
require.NoError(t, err)
|
|
|
|
// Inject the ingestor
|
|
ingestor := &fakeIngestor{}
|
|
client.ingestors["test1"] = ingestor
|
|
|
|
tableMetricGroups := make(map[string][]byte)
|
|
mockmetrics := testutil.MockMetrics()
|
|
for _, m := range mockmetrics {
|
|
metricInBytes, err := serializer.Serialize(m)
|
|
require.NoError(t, err)
|
|
tableMetricGroups[m.Name()] = append(tableMetricGroups[m.Name()], metricInBytes...)
|
|
}
|
|
|
|
format := ingest.FileFormat(ingest.JSON)
|
|
for tableName, tableMetrics := range tableMetricGroups {
|
|
require.NoError(t, client.PushMetrics(format, tableName, tableMetrics))
|
|
createdFakeIngestor := ingestor
|
|
require.EqualValues(t, expectedMetric["metricName"], createdFakeIngestor.actualOutputMetric["name"])
|
|
require.EqualValues(t, expectedMetric["fields"], createdFakeIngestor.actualOutputMetric["fields"])
|
|
require.EqualValues(t, expectedMetric["tags"], createdFakeIngestor.actualOutputMetric["tags"])
|
|
timestampStr := createdFakeIngestor.actualOutputMetric["timestamp"].(string)
|
|
parsedTime, err := time.Parse(time.RFC3339Nano, timestampStr)
|
|
parsedTimeFloat := float64(parsedTime.UnixNano()) / 1e9
|
|
require.NoError(t, err)
|
|
require.InDelta(t, expectedMetric["timestamp"].(float64), parsedTimeFloat, testutil.DefaultDelta)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAlreadyClosed(t *testing.T) {
|
|
plugin := Client{
|
|
logger: testutil.Logger{},
|
|
cfg: &Config{
|
|
IngestionType: QueuedIngestion,
|
|
},
|
|
client: kusto.NewMockClient(),
|
|
}
|
|
require.NoError(t, plugin.Close())
|
|
}
|
|
|
|
type fakeIngestor struct {
|
|
actualOutputMetric map[string]interface{}
|
|
}
|
|
|
|
func (f *fakeIngestor) FromReader(_ context.Context, reader io.Reader, _ ...ingest.FileOption) (*ingest.Result, error) {
|
|
scanner := bufio.NewScanner(reader)
|
|
scanner.Scan()
|
|
firstLine := scanner.Text()
|
|
err := json.Unmarshal([]byte(firstLine), &f.actualOutputMetric)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ingest.Result{}, nil
|
|
}
|
|
|
|
func (*fakeIngestor) FromFile(_ context.Context, _ string, _ ...ingest.FileOption) (*ingest.Result, error) {
|
|
return &ingest.Result{}, nil
|
|
}
|
|
|
|
func (*fakeIngestor) Close() error {
|
|
return nil
|
|
}
|